Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into ri-correctly-set-op…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
bassosimone committed Jun 28, 2024
2 parents ddf00a7 + a73c754 commit 5229771
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 6 deletions.
8 changes: 8 additions & 0 deletions internal/cmd/miniooni/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
// Options contains the options you can set from the CLI.
type Options struct {
Annotations []string
AuthFile string
Emoji bool
ExtraOptions []string
HomeDir string
Expand Down Expand Up @@ -228,6 +229,13 @@ func registerOONIRun(rootCmd *cobra.Command, globalOptions *Options) {
[]string{},
"Path to the OONI Run v2 descriptor to run (may be specified multiple times)",
)
flags.StringVarP(
&globalOptions.AuthFile,
"bearer-token-file",
"",
"",
"Path to a file containing a bearer token for fetching a remote OONI Run v2 descriptor",
)
}

// registerAllExperiments registers a subcommand for each experiment
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/miniooni/oonirun.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func ooniRunMain(ctx context.Context,
logger := sess.Logger()
cfg := &oonirun.LinkConfig{
AcceptChanges: currentOptions.Yes,
AuthFile: currentOptions.AuthFile,
Annotations: annotations,
KVStore: sess.KeyValueStore(),
MaxRuntime: currentOptions.MaxRuntime,
Expand Down
4 changes: 4 additions & 0 deletions internal/oonirun/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ type LinkConfig struct {
// reviewing what it contains or what has changed.
AcceptChanges bool

// AuthFile is OPTIONAL and will add an authentication header to the
// request used for fetching this OONI Run link.
AuthFile string

// Annotations contains OPTIONAL Annotations for the experiment.
Annotations map[string]string

Expand Down
65 changes: 60 additions & 5 deletions internal/oonirun/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ package oonirun
//

import (
"bufio"
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"strings"
"sync/atomic"

"github.com/hexops/gotextdiff"
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
"github.com/ooni/probe-cli/v3/internal/fsx"
"github.com/ooni/probe-cli/v3/internal/httpclientx"
"github.com/ooni/probe-cli/v3/internal/kvstore"
"github.com/ooni/probe-cli/v3/internal/model"
Expand Down Expand Up @@ -63,12 +67,16 @@ type V2Nettest struct {
// getV2DescriptorFromHTTPSURL GETs a v2Descriptor instance from
// a static URL (e.g., from a GitHub repo or from a Gist).
func getV2DescriptorFromHTTPSURL(ctx context.Context, client model.HTTPClient,
logger model.Logger, URL string) (*V2Descriptor, error) {
logger model.Logger, URL, auth string) (*V2Descriptor, error) {
if auth != "" {
// we assume a bearer token
auth = fmt.Sprintf("Bearer %s", auth)
}
return httpclientx.GetJSON[*V2Descriptor](
ctx,
httpclientx.NewEndpoint(URL),
&httpclientx.Config{
Authorization: "", // not needed
Authorization: auth,
Client: client,
Logger: logger,
UserAgent: model.HTTPHeaderUserAgent,
Expand Down Expand Up @@ -140,9 +148,9 @@ func v2DescriptorCacheLoad(fsstore model.KeyValueStore) (*v2DescriptorCache, err
// - err is the error that occurred, or nil in case of success.
func (cache *v2DescriptorCache) PullChangesWithoutSideEffects(
ctx context.Context, client model.HTTPClient, logger model.Logger,
URL string) (oldValue, newValue *V2Descriptor, err error) {
URL, auth string) (oldValue, newValue *V2Descriptor, err error) {
oldValue = cache.Entries[URL]
newValue, err = getV2DescriptorFromHTTPSURL(ctx, client, logger, URL)
newValue, err = getV2DescriptorFromHTTPSURL(ctx, client, logger, URL, auth)
return
}

Expand Down Expand Up @@ -263,7 +271,11 @@ func v2MeasureHTTPS(ctx context.Context, config *LinkConfig, URL string) error {

// pull a possibly new descriptor without updating the old descriptor
clnt := config.Session.DefaultHTTPClient()
oldValue, newValue, err := cache.PullChangesWithoutSideEffects(ctx, clnt, logger, URL)
auth, err := v2MaybeGetAuthenticationTokenFromFile(config.AuthFile)
if err != nil {
logger.Warnf("oonirun: failed to retrieve auth token: %v", err)
}
oldValue, newValue, err := cache.PullChangesWithoutSideEffects(ctx, clnt, logger, URL, auth)
if err != nil {
return err
}
Expand All @@ -290,3 +302,46 @@ func v2MeasureHTTPS(ctx context.Context, config *LinkConfig, URL string) error {
// note: this function gracefully handles nil values
return V2MeasureDescriptor(ctx, config, newValue)
}

func v2MaybeGetAuthenticationTokenFromFile(path string) (string, error) {
if path != "" {
return v2ReadBearerTokenFromFile(path)
}
return "", nil
}

// v2ReadBearerTokenFromFile tries to extract a valid (base64) bearer token from
// the first line of the passed text file.
// If there is an error while reading from the file, the error will be returned.
// If we can read from the file but there's no valid token found, an empty string will be returned.
func v2ReadBearerTokenFromFile(fileName string) (string, error) {
filep, err := fsx.OpenFile(fileName)
if err != nil {
return "", err
}
defer filep.Close()

scanner := bufio.NewScanner(filep)

// Scan the first line
if scanner.Scan() {
line := scanner.Text()

token := strings.TrimSpace(line)

// if this is not a valid base64 token, return empty string
if _, err := base64.StdEncoding.DecodeString(token); err != nil {
return "", nil
}

return token, nil
}

// Check for any scanning error
if err := scanner.Err(); err != nil {
return "", err
}

// Return empty string if file is empty
return "", nil
}
Loading

0 comments on commit 5229771

Please sign in to comment.