Skip to content

Support HTTP authentication for remote action loading #1009

@bmastay-soartech

Description

@bmastay-soartech

Enhancement Request

Summary

fcli * action run supports loading actions from URLs, but ActionLoaderHelper.createSourceInputStream() uses URL.openStream() which doesn't support authentication. This makes it impossible to load actions from authenticated endpoints like Bitbucket Server, GitLab, or private GitHub repos.

Current Behavior

// ActionLoaderHelper.java:434
private static InputStream createSourceInputStream(String source) throws IOException {
    return new URL(source).openStream();
}

Embedding credentials in the URL (https://user:token@host/...) fails when tokens contain special characters (+, /, =) that break Java's URL parser. .netrc is not supported by URL.openStream().

$ fcli ssc action run "https://user:token@bitbucket.example.com/rest/api/latest/.../action.yaml" --on-unsigned=ignore

Caused by: java.io.IOException: Server returned HTTP response code: 401

The same URL works with curl:

$ curl -sf -u "user:token" "https://bitbucket.example.com/rest/api/latest/.../action.yaml" | head -3
# yaml-language-server: $schema=...

Proposed Solution

Support authentication for URL-based action loading via one or more of:

Option A: CLI options for action auth

fcli ssc action run "https://bitbucket.example.com/.../action.yaml" \
  --action-auth-basic "user:token"

# or
fcli ssc action run "https://bitbucket.example.com/.../action.yaml" \
  --action-auth-header "Authorization: Bearer <token>"

Option B: Environment variable

export FCLI_ACTION_AUTH_BASIC="user:token"
# or
export FCLI_ACTION_AUTH_HEADER="Bearer <token>"

fcli ssc action run "https://bitbucket.example.com/.../action.yaml"

Option C: Use HttpURLConnection with Authenticator

Replace URL.openStream() with HttpURLConnection and support credentials-in-URL properly by extracting userInfo from the URL and setting the Authorization header manually:

    private static InputStream createSourceInputStream(String source) throws IOException {
    URL url = new URL(source);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    String userInfo = url.getUserInfo();
    if (userInfo != null) {
        String basicAuth = "Basic " + Base64.getEncoder()
            .encodeToString(userInfo.getBytes(StandardCharsets.UTF_8));
        conn.setRequestProperty("Authorization", basicAuth);
    }
    return conn.getInputStream();
   }

Use Case

We maintain a custom fcli action (check-cmpc-policy.yaml) in a private Bitbucket Server repository and want CI pipelines to load it at runtime without baking it into the container image. This enables versioned, centrally managed actions that can be updated without rebuilding images.

Workaround

Currently we curl the action file with authentication and pass the local path to fcli:

curl -sf -u "${BB_USER}:${BB_TOKEN}" -o /tmp/action.yaml "${ACTION_URL}"
fcli ssc action run file:/tmp/action.yaml --on-unsigned=ignore

Environment

fcli version: 3.19.0
Bitbucket Server 9.4.8
Java 21.0.2 (Temurin)

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions