-
Notifications
You must be signed in to change notification settings - Fork 24
fix IPv6 support in server bind, client dial and table output #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f2de5e5
c2a9a7c
7ff8d28
af98c75
d7a034a
514a292
8069b22
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||
| name: Go | ||||||
| on: | ||||||
| pull_request: | ||||||
| branches: | ||||||
| - master | ||||||
| - main | ||||||
| push: | ||||||
| branches: | ||||||
| - master | ||||||
| - main | ||||||
| jobs: | ||||||
| build: | ||||||
| name: Build and test | ||||||
| runs-on: ubuntu-latest | ||||||
|
Comment on lines
+11
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- workflow ---'
cat -n .github/workflows/go.yml
printf '%s\n' '--- token and permission references ---'
rg -n --hidden -g '.github/**' -e 'GITHUB_TOKEN|permissions:|contents:|pull-requests:|issues:|actions:' . || true
printf '%s\n' '--- workflow files ---'
git ls-files '.github/workflows/*'Repository: minio/hperf Length of output: 1286 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- related workflow ---'
cat -n .github/workflows/vulncheck.yml
printf '%s\n' '--- public repository workflow permissions metadata ---'
curl -sS -L -H 'Accept: application/vnd.github+json' \
https://api.github.com/repos/minio/hperf/actions/permissions/workflow | jq .Repository: minio/hperf Length of output: 1200 🌐 Web query:
💡 Result: In GitHub Actions, the GITHUB_TOKEN is a unique, automatically generated secret used to authenticate workflows [1]. You can control its permissions using the permissions key in your workflow YAML file, which allows you to define granular, least-privilege access for the entire workflow or individual jobs [2][3]. Default Permissions The default permissions for the GITHUB_TOKEN are determined by settings configured at the enterprise, organization, or repository level [2][4]. Administrators can choose between two main options: - Read and write permissions: The GITHUB_TOKEN is granted broad access. - Read repository contents and packages permissions: The GITHUB_TOKEN is restricted to read-only access for these specific scopes [5][4]. If an organization or enterprise enforces a restrictive default, individual repositories cannot override it to be more permissive [5][6]. Conversely, regardless of the repository or organization default, any user with write access to the repository can use the permissions key in a workflow file to further restrict or adjust the token's access for specific jobs [5][7]. Special Cases for Pull Requests - Pull Requests from Forks: For security reasons, workflows triggered by pull_request events from forked repositories are always granted a read-only GITHUB_TOKEN, regardless of the configured repository or organization settings [2][8][9]. - Write Tokens: If you need a workflow to perform write operations (such as pushing code or commenting) on a pull request, you may need to use the pull_request_target event instead, provided the workflow context is trusted [9]. Additionally, there is a setting, Send write tokens to workflows from pull requests, which, if enabled, affects how permissions are applied; if this is not selected, write permissions are downgraded to read-only for pull requests [2][8]. Principle of Least Privilege It is a recommended security practice to explicitly define the permissions for every workflow using the permissions key, rather than relying on default settings [3][10]. By setting unused permissions to none, you reduce the risk of unauthorized access if a workflow or action is compromised [11][10]. Syntax Example To set permissions, add a permissions block to your workflow file: permissions: contents: read issues: write pull-requests: none Citations:
🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re
path = Path(".github/workflows/go.yml")
text = path.read_text()
lines = text.splitlines()
jobs_index = next(i for i, line in enumerate(lines) if line == "jobs:")
permissions_index = next((i for i, line in enumerate(lines) if line == "permissions:"), None)
checkout_default = bool(re.search(r"^\s+uses:\s+actions/checkout@[^#\s]+$", text, re.MULTILINE))
go_commands = [
line.strip()
for line in lines
if re.match(r"^\s+run:\s+go\s+(build|vet|test)\b", line)
]
print({
"permissions_before_jobs": permissions_index is not None and permissions_index < jobs_index,
"checkout_uses_default_token": checkout_default,
"go_commands": go_commands,
})
PYRepository: minio/hperf Length of output: 310 Restrict the workflow token permissions. This workflow uses the default 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||
| strategy: | ||||||
| matrix: | ||||||
| go-version: [ 1.26.x ] | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Fix the YAML lint error. YAMLlint reports extra spaces inside the Proposed fix- go-version: [ 1.26.x ]
+ go-version: [1.26.x]📝 Committable suggestion
Suggested change
🧰 Tools🪛 YAMLlint (1.37.1)[error] 17-17: too many spaces inside brackets (brackets) [error] 17-17: too many spaces inside brackets (brackets) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||
| steps: | ||||||
| - name: Check out code into the Go module directory | ||||||
| uses: actions/checkout@v4 | ||||||
|
Comment on lines
+19
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- workflow ---'
cat -n .github/workflows/go.yml
printf '%s\n' '--- checkout configuration references ---'
rg -n --hidden --glob '!.git/**' 'persist-credentials|actions/checkout|git config' .github README.md 2>/dev/null || true
printf '%s\n' '--- workflow files ---'
git ls-files '.github/workflows/*'Repository: minio/hperf Length of output: 1415 🌐 Web query:
💡 Result: In actions/checkout v4, the persist-credentials input defaults to true [1][2][3]. When this setting is enabled (the default), the action automatically persists the GitHub Actions authentication token in the local git configuration [1][4]. This allows your workflow scripts to run authenticated git commands (e.g., git push or git fetch) without requiring additional configuration [1][4]. The action ensures this token is removed during the post-job cleanup process [1][4]. If you wish to disable this behavior for security reasons or if you are using a different authentication method, you can opt out by setting persist-credentials to false in your workflow file [1][4]: - uses: actions/checkout@v4 with: persist-credentials: false Citations:
🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- all workflow commands ---'
for file in $(git ls-files '.github/workflows/*'); do
printf '\n[%s]\n' "$file"
cat -n "$file"
done
printf '%s\n' '--- repository execution inputs ---'
git ls-files | sed -n '1,120p'Repository: minio/hperf Length of output: 3140 Disable checkout credential persistence. Subsequent steps execute repository-controlled Go code. Set 🧰 Tools🪛 zizmor (1.29.0)[warning] 19-20: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [error] 20-20: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||
| - uses: actions/setup-go@v5 | ||||||
|
Comment on lines
+20
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- workflow ---'
cat -n .github/workflows/go.yml
printf '%s\n' '--- action references and repository policy ---'
rg -n --hidden -g '!node_modules' -g '!dist' 'actions/(checkout|setup-go)@|pin.*SHA|immutable|step-security' .github README.md CONTRIBUTING.md 2>/dev/null || trueRepository: minio/hperf Length of output: 1468 Pin both GitHub Actions to immutable commit SHAs. Replace 🧰 Tools🪛 zizmor (1.29.0)[error] 20-20: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 21-21: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||
| with: | ||||||
| go-version: ${{ matrix.go-version }} | ||||||
| check-latest: true | ||||||
| - name: Check formatting | ||||||
| run: test -z "$(gofmt -l .)" || (gofmt -l . && exit 1) | ||||||
| shell: bash | ||||||
| - name: Build | ||||||
| run: go build ./... | ||||||
| shell: bash | ||||||
| - name: Vet | ||||||
| run: go vet ./... | ||||||
| shell: bash | ||||||
| - name: Test | ||||||
| run: go test -race ./... | ||||||
| shell: bash | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -105,6 +105,42 @@ hperf supports flexible host specification: | |
| ./hperf latency --hosts file:/home/user/hosts.txt | ||
| ``` | ||
|
|
||
| ### IPv6 | ||
|
|
||
| IPv6 works everywhere IPv4 does. Addresses are accepted with or without | ||
| brackets and are canonicalized internally, so `2001:db8::1`, `[2001:db8::1]` | ||
| and `2001:0db8:0000:0000:0000:0000:0000:0001` all refer to the same host: | ||
|
|
||
| ```bash | ||
| # IPv6 literals, ellipsis patterns and scoped link-local addresses | ||
| ./hperf latency --hosts 2001:db8::1,2001:db8::2 | ||
| ./hperf latency --hosts 2001:db8::{1...10} | ||
| ./hperf latency --hosts fe80::1%eth0,fe80::2%eth0 | ||
| ``` | ||
|
|
||
| Servers need a listener on an IPv6 address: | ||
|
|
||
| ```bash | ||
| # Dual-stack: accepts IPv4 and IPv6 on every interface | ||
| ./hperf server --address '[::]:9010' | ||
|
|
||
| # A single IPv6 address, with the same address reported in results | ||
| ./hperf server --address '[2001:db8::1]:9010' --real-ip 2001:db8::1 | ||
| ``` | ||
|
|
||
| Note that a wildcard bind (`0.0.0.0:9010` or `[::]:9010`, including the | ||
| default) listens for both address families. Bind a specific address if you | ||
| need to restrict the server to one family. The server API is unauthenticated, | ||
| so this matters when the port is reachable from untrusted networks. | ||
|
Comment on lines
+121
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Qualify the wildcard-listener explanation in both documentation locations. Fiber's 📍 Affects 2 files
🤖 Prompt for AI Agents |
||
|
|
||
| When `--hosts` contains hostnames, `--ip-family` picks the address family they | ||
| resolve to (`auto`, `4` or `6`), and `--dns-server` resolves them through a | ||
| specific DNS server: | ||
|
|
||
| ```bash | ||
| ./hperf latency --hosts node{1...4}.example.com --ip-family 6 | ||
| ``` | ||
|
|
||
| ## Understanding Test Results | ||
|
|
||
| ### Real-Time Output | ||
|
|
@@ -213,6 +249,8 @@ Find optimal buffer/payload sizes for your workload: | |
| | `--request-delay` | 0 | Delay between requests in milliseconds | | ||
| | `--save` | true | Save test results on servers | | ||
| | `--insecure` | false | Use HTTP instead of HTTPS | | ||
| | `--dns-server` | (system) | DNS server used to resolve hostnames in `--hosts` | | ||
| | `--ip-family` | auto | Address family for hostname resolution: `auto`, `4` or `6` | | ||
| | `--debug` | false | Enable debug output | | ||
|
|
||
| ### Environment Variables | ||
|
|
@@ -271,6 +309,10 @@ docker run -p 9010:9010 minio/hperf:latest server --address 0.0.0.0:9010 | |
| **Symptom**: Unusually high throughput or low latency results | ||
| **Solution**: Ensure `--real-ip` matches the external IP used for inter-server communication | ||
|
|
||
| ### Server exits with "unable to listen on ..." | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Add a blank line before the new heading. Line 312 violates Markdownlint rule MD022 because the heading is not preceded by a blank line. 🧰 Tools🪛 markdownlint-cli2 (0.23.2)[warning] 312-312: Headings should be surrounded by blank lines (MD022, blanks-around-headings) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| **Symptom**: The server stops right after start | ||
| **Solution**: The bind address is not usable on this host. `--address '[::]:9010'` is the dual-stack wildcard; an IPv6 literal has to be bracketed (`'[2001:db8::1]:9010'`) | ||
|
|
||
| ### No data points received | ||
| **Symptom**: Client shows no statistics during test | ||
| **Solution**: Check firewall rules, verify servers can reach each other on the specified port, enable `--debug` | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| // Copyright (c) 2015-2024 MinIO, Inc. | ||
| // | ||
| // This file is part of MinIO Object Storage stack | ||
| // | ||
| // This program is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU Affero General Public License as published by | ||
| // the Free Software Foundation, either version 3 of the License, or | ||
| // (at your option) any later version. | ||
| // | ||
| // This program is distributed in the hope that it will be useful | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU Affero General Public License for more details. | ||
| // | ||
| // You should have received a copy of the GNU Affero General Public License | ||
| // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
|
||
| package client | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/minio/hperf/shared" | ||
| ) | ||
|
|
||
| func TestGrowHostColumns(t *testing.T) { | ||
| initHeaders() | ||
|
|
||
| if grew := growHostColumns([]shared.DP{{Local: "10.10.1.2", Remote: "10.10.1.3:9010"}}); grew { | ||
| t.Error("IPv4 addresses should fit the default column width") | ||
| } | ||
| if headerSlice[Local].width != 15 || headerSlice[Remote].width != 15 { | ||
| t.Errorf("widths changed for IPv4: local=%d remote=%d", headerSlice[Local].width, headerSlice[Remote].width) | ||
| } | ||
|
|
||
| v6 := "2607:6bc0:8107:432:8e91:3aff:fec5:79ee" | ||
| if grew := growHostColumns([]shared.DP{{Local: v6, Remote: "[" + v6 + "]:9010"}}); !grew { | ||
| t.Error("IPv6 addresses should widen the host columns") | ||
| } | ||
| if headerSlice[Local].width != len(v6) || headerSlice[Remote].width != len(v6) { | ||
| t.Errorf("widths not grown to %d: local=%d remote=%d", len(v6), headerSlice[Local].width, headerSlice[Remote].width) | ||
| } | ||
|
|
||
| if grew := growHostColumns([]shared.DP{{Local: "10.10.1.2", Remote: "10.10.1.3:9010"}}); grew { | ||
| t.Error("columns should not shrink or report a change for narrower addresses") | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win
Cancel superseded workflow runs.
This workflow runs for both pull requests and pushes. Add a
concurrencygroup keyed by the pull request or branch, withcancel-in-progress: true, so obsolete build and test runs do not consume runners or report stale results.🧰 Tools
🪛 YAMLlint (1.37.1)
[warning] 2-2: truthy value should be one of [false, true]
(truthy)
🪛 zizmor (1.29.0)
[warning] 2-10: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
🤖 Prompt for AI Agents
Source: Linters/SAST tools