detached 388d3be

cli_oidc.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package app
4
5import (
6	"connectrpc.com/connect"
7	"github.com/spf13/cobra"
8
9	"bnema.dev/ermite-api/gen/ermite"
10)
11
12// jsonOIDCRotation is the stable JSON shape of `oidc rotate-key --json`.
13type jsonOIDCRotation struct {
14	Issuer       string  `json:"issuer"`
15	Kid          string  `json:"kid"`
16	RetiredKid   *string `json:"retired_kid"`
17	RetiredUntil *string `json:"retired_until"`
18}
19
20func newOIDCCmd(env *cliEnv) *cobra.Command {
21	oidc := &cobra.Command{
22		Use:   "oidc",
23		Short: "Manage the OIDC provider of CI jobs",
24		Long: "The server issues OIDC ID tokens to the CI jobs of trusted runs that have `permissions: id-token:\n" +
25			"write`, as GitHub does: a relying party (Vault, a cloud) that trusts the issuer\n" +
26			"<public URL>/-/oidc exchanges them for credentials. It signs them with its own key, sealed with\n" +
27			"ERMITE_SECRETS_KEY: a server without that key issues none. Needs a server with the ci.oidc\n" +
28			"feature (see `ermite version`).",
29	}
30	oidc.AddCommand(newOIDCRotateKeyCmd(env))
31	return oidc
32}
33
34func newOIDCRotateKeyCmd(env *cliEnv) *cobra.Command {
35	cmd := &cobra.Command{
36		Use:   "rotate-key",
37		Short: "Replace the key that signs the ID tokens",
38		Long: "Generate a new signing key for the ID tokens. The new key signs at once; the previous one stays\n" +
39			"in the JWKS (<issuer>/.well-known/jwks) for 24 hours, so that the tokens it signed verify until they\n" +
40			"expire. Needs owner rights: the admin token, or a token with every scope, no repository list\n" +
41			"and no branch prefixes.\n\n" +
42			"JSON fields (--json): issuer, kid, retired_kid and retired_until (RFC 3339 UTC; both null when\n" +
43			"there was no previous key).",
44		Args: cobra.NoArgs,
45	}
46	asJSON := addJSONFlag(cmd)
47	cmd.RunE = func(cmd *cobra.Command, _ []string) error {
48		c, err := env.client(cmd)
49		if err != nil {
50			return err
51		}
52		res, err := c.Server().RotateOIDCKey(env.ctx(cmd), connect.NewRequest(&ermite.RotateOIDCKeyRequest{}))
53		if err != nil {
54			return c.Describe(err)
55		}
56		r := res.Msg
57		out := cmd.OutOrStdout()
58		if *asJSON {
59			j := jsonOIDCRotation{Issuer: r.GetIssuer(), Kid: r.GetKid(), RetiredUntil: jsonTime(r.GetRetiredUntil())}
60			if k := r.GetRetiredKid(); k != "" {
61				j.RetiredKid = &k
62			}
63			return writeJSON(out, j)
64		}
65		pairs := [][2]string{{"issuer", r.GetIssuer()}, {"kid", r.GetKid()}}
66		if r.GetRetiredKid() != "" {
67			pairs = append(pairs, [2]string{"retired kid", r.GetRetiredKid()}, [2]string{"published until", shortTime(r.GetRetiredUntil(), "")})
68		}
69		return fields(out, pairs)
70	}
71	return cmd
72}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 45

↑↓ moveenter openesc close