Skip to content

Commit 696ac2d

Browse files
ewelsjorgeechristopher-hakkaartpditommaso
authored
New command group: nextflow auth (#6380)
Signed-off-by: Phil Ewels <[email protected]> Signed-off-by: jorgee <[email protected]> Signed-off-by: Christopher Hakkaart <[email protected]> Signed-off-by: Paolo Di Tommaso <[email protected]> Co-authored-by: jorgee <[email protected]> Co-authored-by: Christopher Hakkaart <[email protected]> Co-authored-by: Paolo Di Tommaso <[email protected]>
1 parent 67a5320 commit 696ac2d

File tree

12 files changed

+3638
-3
lines changed

12 files changed

+3638
-3
lines changed

docs/install.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,14 @@ The standalone distribution will still download core and third-party plugins as
164164
165165
You can launch workflows directly from [Seqera Platform](https://seqera.io/platform/) without installing Nextflow locally.
166166
167-
Launching from Seqera Platform provides you with:
167+
Launching from Seqera provides you with:
168168
169169
- User-friendly launch interfaces.
170170
- Automated cloud infrastructure creation.
171171
- Organizational user management.
172172
- Advanced analytics with resource optimization.
173173
174174
Seqera Cloud Basic is free for small teams. Researchers at qualifying academic institutions can apply for free access to Seqera Cloud Pro.
175-
See the [Seqera Platform documentation](https://docs.seqera.io/platform) for tutorials to get started.
175+
See [Seqera Platform Cloud](https://docs.seqera.io/platform) to get started.
176+
177+
If you have installed Nextflow locally, you can use the {ref}`nextflow auth <cli-auth>` command to authenticate with Seqera and automatically configure workflow monitoring.

docs/reference/cli.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,80 @@ Available options:
5252

5353
## Commands
5454

55+
(cli-auth)=
56+
57+
### `auth`
58+
59+
:::{versionadded} 25.09.0-edge
60+
:::
61+
62+
Manage Seqera Platform authentication.
63+
64+
**Usage**
65+
66+
```console
67+
$ nextflow auth <subcommand> [options]
68+
```
69+
70+
**Description**
71+
72+
The `auth` command provides authentication and configuration management for Seqera. For Seqera Cloud, it uses an OAuth2 authentication flow generate and save a Personal Access Token (PAT) locally. For Seqera Enterprise installations, it uses direct PAT authentication. Credentials are saved to `~/.nextflow/seqera-auth.config`.
73+
74+
**Options**
75+
76+
`-h, -help`
77+
: Prints the command usage information.
78+
79+
**Subcommands**
80+
81+
`login`
82+
: Authenticates with Seqera and saves credentials. Sets Seqera primary compute environment, monitoring, and workspace.
83+
: The following options are available:
84+
85+
`-u, -url`
86+
: Specifies your Seqera API endpoint (default: `https://api.cloud.seqera.io`)
87+
88+
`logout`
89+
: Removes Seqera authentication and revokes the Seqera Cloud access token (if applicable).
90+
91+
`config`
92+
: Sets Seqera primary compute environment, monitoring, and workspace.
93+
94+
`status`
95+
: Shows Seqera authentication status and configuration.
96+
97+
**Examples**
98+
99+
Authenticate with Seqera Cloud:
100+
101+
```console
102+
$ nextflow auth login
103+
```
104+
105+
Authenticate with an Enterprise installation:
106+
107+
```console
108+
$ nextflow auth login -u https://tower.example.com/api
109+
```
110+
111+
View current authentication status:
112+
113+
```console
114+
$ nextflow auth status
115+
```
116+
117+
Configure Seqera settings:
118+
119+
```console
120+
$ nextflow auth config
121+
```
122+
123+
Remove authentication:
124+
125+
```console
126+
$ nextflow auth logout
127+
```
128+
55129
(cli-clean)=
56130

57131
### `clean`
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
/*
2+
* Copyright 2013-2025, Seqera Labs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package nextflow.cli
18+
19+
import com.beust.jcommander.Parameter
20+
import com.beust.jcommander.Parameters
21+
import groovy.transform.CompileStatic
22+
import groovy.util.logging.Slf4j
23+
import nextflow.Const
24+
import nextflow.SysEnv
25+
import nextflow.config.ConfigBuilder
26+
import nextflow.exception.AbortOperationException
27+
import nextflow.platform.PlatformHelper
28+
import nextflow.plugin.Plugins
29+
import org.fusesource.jansi.Ansi
30+
import org.pf4j.ExtensionPoint
31+
32+
import java.nio.file.Paths
33+
34+
import static org.fusesource.jansi.Ansi.*
35+
36+
import java.nio.file.Files
37+
import java.nio.file.Path
38+
import java.nio.file.StandardOpenOption
39+
import java.util.concurrent.CompletableFuture
40+
import java.util.concurrent.TimeUnit
41+
import java.util.regex.Pattern
42+
43+
/**
44+
* Implements the 'nextflow auth' commands
45+
*
46+
* @author Phil Ewels <[email protected]>
47+
*/
48+
@Slf4j
49+
@CompileStatic
50+
@Parameters(commandDescription = "Manage Seqera Platform authentication")
51+
class CmdAuth extends CmdBase implements UsageAware {
52+
53+
interface SubCmd {
54+
String getName()
55+
void apply(List<String> result)
56+
void usage(List<String> result)
57+
}
58+
59+
interface AuthCommand extends ExtensionPoint {
60+
void login(String url)
61+
void logout()
62+
void config()
63+
void status()
64+
}
65+
66+
static public final String NAME = 'auth'
67+
68+
private List<SubCmd> commands = []
69+
70+
private AuthCommand operation
71+
72+
String getName() {
73+
return NAME
74+
}
75+
76+
@Parameter(hidden = true)
77+
List<String> args
78+
79+
@Parameter(names = ['-u', '-url'], description = 'Seqera Platform API endpoint')
80+
String apiUrl
81+
82+
CmdAuth() {
83+
commands.add(new LoginCmd())
84+
commands.add(new LogoutCmd())
85+
commands.add(new ConfigCmd())
86+
commands.add(new StatusCmd())
87+
}
88+
89+
void usage() {
90+
usage(args)
91+
}
92+
93+
void usage(List<String> args) {
94+
List<String> result = []
95+
if (!args) {
96+
result << this.getClass().getAnnotation(Parameters).commandDescription()
97+
result << 'Usage: nextflow auth <sub-command> [options]'
98+
result << ''
99+
result << 'Commands:'
100+
result << ' login Authenticate with Seqera Platform'
101+
result << ' logout Remove authentication and revoke access token'
102+
result << ' status Show current authentication status and configuration'
103+
result << ' config Configure Seqera Platform settings'
104+
result << ''
105+
} else {
106+
def sub = commands.find { it.name == args[0] }
107+
if (sub)
108+
sub.usage(result)
109+
else {
110+
throw new AbortOperationException("Unknown auth sub-command: ${args[0]}")
111+
}
112+
}
113+
println result.join('\n').toString()
114+
}
115+
116+
@Override
117+
void run() {
118+
if (!args) {
119+
usage()
120+
return
121+
}
122+
// load the Auth command implementation
123+
this.operation = loadOperation()
124+
if( !operation )
125+
throw new IllegalStateException("Unable to load auth extensions.")
126+
// consume the first argument
127+
getCmd(args).apply(args.drop(1))
128+
}
129+
130+
protected AuthCommand loadOperation(){
131+
// setup the plugins system and load the secrets provider
132+
Plugins.init()
133+
// load the config
134+
Plugins.start('nf-tower')
135+
// get Auth command operations implementation from plugins
136+
return Plugins.getExtension(AuthCommand)
137+
}
138+
139+
protected SubCmd getCmd(List<String> args) {
140+
def cmd = commands.find { it.name == args[0] }
141+
if (cmd) {
142+
return cmd
143+
}
144+
145+
def matches = commands.collect { it.name }.closest(args[0])
146+
def msg = "Unknown auth sub-command: ${args[0]}"
147+
if (matches)
148+
msg += " -- Did you mean one of these?\n" + matches.collect { " $it" }.join('\n')
149+
throw new AbortOperationException(msg)
150+
}
151+
152+
//
153+
// nextflow auth login
154+
//
155+
class LoginCmd implements SubCmd {
156+
157+
@Override
158+
String getName() { 'login' }
159+
160+
@Override
161+
void apply(List<String> args) {
162+
if (args.size() > 0) {
163+
throw new AbortOperationException("Too many arguments for ${name} command")
164+
}
165+
operation.login(apiUrl)
166+
}
167+
168+
169+
170+
@Override
171+
void usage(List<String> result) {
172+
// Read config to get the actual resolved endpoint value
173+
final builder = new ConfigBuilder().setHomeDir(Const.APP_HOME_DIR).setCurrentDir(Const.APP_HOME_DIR)
174+
final config = builder.buildConfigObject().flatten()
175+
final towerConfig = config.findAll { it.key.toString().startsWith('tower.') }
176+
.collectEntries { k, v -> [(k.toString().substring(6)): v] }
177+
def defaultEndpoint = PlatformHelper.getEndpoint(towerConfig, SysEnv.get())
178+
179+
result << 'Authenticate with Seqera Platform'
180+
result << "Usage: nextflow auth $name [-u <endpoint>]".toString()
181+
result << ''
182+
result << 'Options:'
183+
result << " -u, -url <endpoint> Seqera Platform API endpoint (default: ${defaultEndpoint})".toString()
184+
result << ''
185+
result << 'This command will:'
186+
result << ' 1. Display a URL and device code for OAuth2 authentication (Cloud) or prompt for PAT (Enterprise)'
187+
result << ' 2. Wait for user to complete authentication in web browser'
188+
result << ' 3. Generate and save access token to home-directory Nextflow config'
189+
result << ' 4. Configure tower.accessToken, tower.endpoint, and tower.enabled settings'
190+
result << ''
191+
}
192+
}
193+
194+
class LogoutCmd implements SubCmd {
195+
196+
@Override
197+
String getName() { 'logout' }
198+
199+
@Override
200+
void apply(List<String> args) {
201+
if (args.size() > 0) {
202+
throw new AbortOperationException("Too many arguments for ${name} command")
203+
}
204+
operation.logout()
205+
}
206+
207+
208+
@Override
209+
void usage(List<String> result) {
210+
result << 'Log out and remove Seqera Platform authentication'
211+
result << "Usage: nextflow auth $name".toString()
212+
result << ''
213+
result << 'This command will:'
214+
result << ' 1. Check if tower.accessToken is configured'
215+
result << ' 2. Validate the token with Seqera Platform'
216+
result << ' 3. Delete the PAT from Platform (only if Seqera Platform Cloud)'
217+
result << ' 4. Remove the authentication from Nextflow config'
218+
result << ''
219+
}
220+
}
221+
222+
//
223+
// nextflow auth config
224+
//
225+
class ConfigCmd implements SubCmd {
226+
227+
@Override
228+
String getName() { 'config' }
229+
230+
@Override
231+
void apply(List<String> args) {
232+
if (args.size() > 0) {
233+
throw new AbortOperationException("Too many arguments for ${name} command")
234+
}
235+
236+
operation.config()
237+
}
238+
239+
240+
@Override
241+
void usage(List<String> result) {
242+
result << 'Configure Seqera Platform settings'
243+
result << "Usage: nextflow auth $name".toString()
244+
result << ''
245+
result << 'This command will:'
246+
result << ' 1. Check authentication status'
247+
result << ' 2. Configure tower.enabled setting for workflow monitoring'
248+
result << ' 3. Configure default workspace (tower.workspaceId)'
249+
result << ''
250+
}
251+
}
252+
253+
class StatusCmd implements SubCmd {
254+
255+
@Override
256+
String getName() { 'status' }
257+
258+
@Override
259+
void apply(List<String> args) {
260+
if (args.size() > 0) {
261+
throw new AbortOperationException("Too many arguments for ${name} command")
262+
}
263+
operation.status()
264+
}
265+
266+
267+
@Override
268+
void usage(List<String> result) {
269+
result << 'Show authentication status and configuration'
270+
result << "Usage: nextflow auth $name".toString()
271+
result << ''
272+
result << 'This command shows:'
273+
result << ' - Authentication status (yes/no) and source'
274+
result << ' - API endpoint and source'
275+
result << ' - Monitoring enabled status and source'
276+
result << ' - Default workspace and source'
277+
result << ' - System health status (API connection and authentication)'
278+
result << ''
279+
}
280+
}
281+
}

0 commit comments

Comments
 (0)