Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 0.3.1 (2026-06-11)

* OAuth browser login: `ucloud auth login` / `ucloud auth logout` (RFC 8252 loopback auto-capture, `--no-browser` fallback)
* automatic token lifecycle: proactive refresh before expiry, reactive refresh-and-replay on auth failure (RetCode 174), flock-serialized rotation safe for concurrent processes
* atomic temp+rename writes for config/credential files
* `auth_mode` picks exactly one credential mechanism per profile; AK/SK profiles unchanged
* fix: `config update --base-url` no longer validates against the old gateway
* fix: login validates an existing project_id against the logged-in account
* fix: `init` on an OAuth profile persists the switch back to AK/SK
* token redaction across all log sinks; panic output redacted

## 0.3.0 (2024-09-20)

* support naming in batch on creating uhost
Expand Down
75 changes: 75 additions & 0 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,81 @@ $ ucloud config update --profile xxx --region cn-sh2
$ ucloud config --help
```

## 认证方式

UCloud CLI 支持两种认证方式,请根据使用场景选择:

| 使用场景 | 推荐方式 |
| --- | --- |
| 交互终端上的人类用户 | OAuth 浏览器登录:`ucloud auth login`(推荐) |
| 脚本、CI/CD 等无人值守自动化 | AK/SK profile:`ucloud init` 或 `ucloud config` |

### 浏览器登录(OAuth)

```
$ ucloud auth login
```

执行过程:

1. CLI 在 127.0.0.1 的临时端口上启动一个本地回调 server,并打开浏览器访问 UCloud 授权页。如果浏览器没有自动打开,复制终端打印的 URL 手动打开即可。
2. 在浏览器中登录并授权后,浏览器会跳转到 `http://localhost:<port>/authorization`,CLI 自动捕获授权码并展示「登录成功」页面——全程无需复制粘贴,关闭页面回到终端即可。
3. CLI 用授权码换取 token 并保存。如果当前 profile 还没有配置 region/zone/project,会自动获取并配置默认值:

```
Configured default region:cn-bj2 zone:cn-bj2-02
Configured default project:org-xxxxxx Default
Logged in as you@example.com, token valid until 18:30
```

### 手工回退(本机无浏览器)

SSH 会话或无图形界面的机器,请加 `--no-browser`:

```
$ ucloud auth login --no-browser
```

CLI 会打印授权 URL 而不是打开浏览器。在任意设备上打开该 URL,登录并授权后,浏览器会跳转到一个**无法打开的** `http://localhost:<port>/authorization?...` 页面——**这是预期行为**。把地址栏中的完整 URL 复制下来,粘贴回终端即可。

默认模式下同样存在这条粘贴回退路径:如果自动捕获在 3 分钟内没有收到回调,CLI 会打印 "Automatic capture timed out. Paste the callback URL here as a fallback:" 并等待粘贴回调 URL。

### Token 存储与有效期

- Token 存储在 `~/.ucloud/credential.json`,文件权限 0600。
- access token 有效期约 1 小时,到期后通过 refresh token 静默续期,全程无感知。续期发生在使用时:运行命令时 CLI 会先检查并刷新临期 token;若网关在命令执行中拒绝 token,也会自动刷新并重试。没有后台常驻进程。
- refresh token 当前有效期为 7 天,且每次续期都会轮换出新的 7 天有效期——只要 7 天内用过一次 CLI,登录态就一直延续;连续 7 天未使用后,下次命令会提示重新执行 `ucloud auth login`。
- 登录态会一直保持,直到 refresh token 在服务端过期,或执行 `ucloud auth logout`。logout 只删除当前 profile 的本地 token,不会动已存储的 AK/SK。退出 UCloud 网页控制台不影响 CLI 登录态。

### 一个 profile 只用一种认证方式

- 每个 profile 同一时刻只使用一种认证方式,可在 `ucloud config list` 的 `AuthMode` 列查看(`oauth` 为浏览器登录,空值为 AK/SK 签名)。
- 执行 `ucloud auth login` 会把当前 profile 切换到 OAuth 模式;已有的 AK/SK 仍保留在配置中,但不再参与签名。
- 在 OAuth 模式的 profile 上执行 `ucloud init`,会先要求确认,确认后才切回 AK/SK。
- 命令行同时传入 `--public-key` 和 `--private-key` 时始终优先生效:该次调用使用 AK/SK 签名,与 profile 的认证模式无关。

### 代理

OAuth token 请求遵循标准的 `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` 环境变量。

### 使用限制

- **OAuth 登录按机器隔离。** 不要在多台机器之间拷贝或共享 `~/.ucloud`:refresh token 每次续期都会轮换,一台机器续期会把另一台「挤」下线。多机或共享场景请使用 AK/SK profile。
- **降级会丢失 token。** 旧版本 ucloud-cli 不认识 token 字段,重写配置文件时会静默丢弃它们。降级后请重新执行 `ucloud auth login`。

### 故障排查

| 现象 / 报错 | 处理方法 |
| --- | --- |
| `authorization code or refresh token expired or already used (each code works only once)` | 每个授权码只能使用一次且很快过期。重新执行 `ucloud auth login` 并尽快完成流程。 |
| `state mismatch: the pasted URL likely comes from a previous login attempt` | 粘贴的是上一次登录尝试的回调 URL。重新执行 `ucloud auth login`,并粘贴本次的 URL。 |
| `Login expired for profile '<name>'` | refresh token 已失效。重新执行 `ucloud auth login`。 |
| `cannot reach oauth server ... (check network or proxy settings)` | 网络或代理问题。检查网络连通性以及 `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` 设置。 |
| `'ucloud auth login' requires an interactive terminal` | 当前处于 CI 或管道(非交互)环境。OAuth 登录面向交互人类用户,自动化场景请改用 AK/SK profile。 |
| 浏览器没有自动打开 | 复制终端打印的 URL 手动打开,或改用 `--no-browser`。 |
| (手工模式)浏览器提示 localhost 页面无法打开 | 预期行为——手工模式下 CLI 并未监听该端口。复制地址栏中的完整 URL 粘贴回终端即可。 |
| (手工模式)localhost 页面显示了其他本地程序的内容 | 无害——恰好有其他程序监听了该端口。只有地址栏里的 URL 有用,复制粘贴即可。 |

## 举例说明

用UCloud CLI在尼日利亚创建数据中心创建一台主机并绑定一个外网IP,然后配置GlobalSSH加速,加速中国大陆到目的主机的SSH登陆
Expand Down
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,81 @@ For more information, run:
$ ucloud config --help
```

## Authentication

The UCloud CLI supports two ways to authenticate. Pick one based on how you use the CLI:

| You are | Use |
| --- | --- |
| A human at an interactive terminal | OAuth browser login: `ucloud auth login` (recommended) |
| Scripts, CI/CD or other unattended automation | AK/SK profile: `ucloud init` or `ucloud config` |

### Log in via browser (OAuth)

```
$ ucloud auth login
```

What happens:

1. The CLI starts a temporary local callback server on an ephemeral 127.0.0.1 port and opens your browser at the UCloud authorization page. If the browser does not open, copy the printed URL and open it manually.
2. You log in and approve. The browser is redirected to `http://localhost:<port>/authorization`, where the CLI captures the authorization code automatically and shows a "Login successful" page — no copy-paste needed. Just close the tab and return to the terminal.
3. The CLI exchanges the code for tokens and saves them. If the profile has no region/zone/project configured yet, it also fetches and configures the defaults:

```
Configured default region:cn-bj2 zone:cn-bj2-02
Configured default project:org-xxxxxx Default
Logged in as you@example.com, token valid until 18:30
```

### Manual fallback (no browser on this machine)

For SSH sessions or headless machines, pass `--no-browser`:

```
$ ucloud auth login --no-browser
```

The CLI prints the authorization URL instead of opening a browser. Open it on any device, log in and approve. The browser will then be redirected to a `http://localhost:<port>/authorization?...` page that **cannot open — this is expected**. Copy the FULL URL from the address bar and paste it back into the terminal.

The same paste prompt is also used as a fallback in the default mode: if the automatic capture does not receive the callback within 3 minutes, the CLI prints "Automatic capture timed out. Paste the callback URL here as a fallback:" and waits for the pasted URL.

### Token storage and lifetime

- Tokens are stored in `~/.ucloud/credential.json` with file mode 0600.
- The access token is valid for about 1 hour and is renewed silently via the refresh token — no action needed from you. Renewal happens on use: when you run a command, the CLI refreshes the token if it is about to expire, and also recovers automatically if the gateway rejects a token mid-command. There is no background daemon.
- The refresh token is currently valid for 7 days and is replaced with a fresh one on every renewal, so any use of the CLI within that window keeps you logged in indefinitely. After 7 days without use, the next command asks you to run `ucloud auth login` again.
- You stay logged in until the refresh token expires on the server side, or until you run `ucloud auth logout`. Logout only removes the locally stored tokens of the current profile; it does not touch any stored AK/SK keys. Logging out of the UCloud web console does not affect CLI sessions.

### One profile, one auth method

- Each profile uses exactly one auth method at a time, shown in the `AuthMode` column of `ucloud config list` (`oauth` for browser login, empty for AK/SK signing).
- Running `ucloud auth login` switches the current profile to OAuth. Existing AK/SK keys are kept stored but no longer used for signing.
- Running `ucloud init` on an OAuth profile asks for confirmation before switching the profile back to AK/SK.
- Passing both `--public-key` and `--private-key` flags on a command always takes precedence: that invocation uses AK/SK signing regardless of the profile's auth mode.

### Proxies

OAuth token requests honor the standard `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` environment variables.

### Limitations

- **OAuth login is per machine.** Do not copy or share `~/.ucloud` across machines: the refresh token rotates on every renewal, so a renewal on one machine logs the other machine out. For multi-machine or shared setups, use an AK/SK profile.
- **Downgrading drops tokens.** Older ucloud-cli versions do not know the token fields and silently drop them when rewriting the config files. After downgrading, run `ucloud auth login` again.

### Troubleshooting

| Symptom / message | What to do |
| --- | --- |
| `authorization code or refresh token expired or already used (each code works only once)` | Each authorization code works only once and expires quickly. Run `ucloud auth login` again and complete the flow promptly. |
| `state mismatch: the pasted URL likely comes from a previous login attempt` | You pasted a callback URL from an earlier attempt. Run `ucloud auth login` again and paste the URL from THIS attempt. |
| `Login expired for profile '<name>'` | The refresh token is no longer valid. Run `ucloud auth login` again. |
| `cannot reach oauth server ... (check network or proxy settings)` | Network or proxy issue. Check connectivity and your `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` settings. |
| `'ucloud auth login' requires an interactive terminal` | You are in CI or piping stdin. OAuth login is for interactive humans; use an AK/SK profile instead. |
| Browser did not open | Copy the URL printed in the terminal and open it manually, or use `--no-browser`. |
| (manual mode) browser shows the localhost page cannot open | Expected — the CLI is not listening in manual mode. Copy the full URL from the address bar and paste it into the terminal. |
| (manual mode) the localhost page shows unexpected content from another local program | Harmless — something else happens to listen on that port. Only the URL in the address bar matters; copy and paste it. |

## For example

I want to create a uhost in Nigeria (region: air-nigeria) and bind a public IP, and then configure GlobalSSH to accelerate efficiency of SSH service beyond China mainland.
Expand Down
Loading