vaultkit 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/lib/vkit/cli/base_cli.rb +1 -1
- data/lib/vkit/cli/commands/approval_command.rb +21 -9
- data/lib/vkit/cli/commands/approval_roles.rb +31 -0
- data/lib/vkit/cli/commands/approval_watch_command.rb +7 -1
- data/lib/vkit/cli/commands/login_command.rb +11 -0
- data/lib/vkit/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64b133877fe2a21e147efaa74745e3322197ca6dda0ba89472d4fb61bd12d533
|
|
4
|
+
data.tar.gz: 83621550f7ae8fcb3b79fb3a67ba8bfffec44459c3e874c33894eefdcc8dfe24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3d187229cc2d2e622fad6de0b48d4876d3de654bc20d949307c4d8b3ac74e6e5bdd0a73ef8b00b6dc2f0cc652aac1be04ccff889c961fe84994a2d228edc0a66
|
|
7
|
+
data.tar.gz: 522e340b74582402669aade2b1dc8d8581d8c1d1edd0409a07277522d1e564925a07c9d583d78766e581f957ccb8c03676332e1e513b1fc51040c051be07ec73
|
data/README.md
CHANGED
|
@@ -443,17 +443,19 @@ vkit approval:approve <REQUEST_ID> [--ttl SECONDS] [--notes "..."]
|
|
|
443
443
|
```
|
|
444
444
|
|
|
445
445
|
**Options:**
|
|
446
|
-
- `--ttl` — Grant lifetime in seconds
|
|
446
|
+
- `--ttl` — Grant lifetime in seconds. Defaults to the policy's TTL, which is also the maximum: a longer value is capped.
|
|
447
447
|
- `--notes` — Approval notes (optional)
|
|
448
448
|
|
|
449
|
+
When a request needs several approver roles, each role signs off separately. Until the last one has, `approve` prints the roles still waiting instead of a grant.
|
|
450
|
+
|
|
449
451
|
**Examples:**
|
|
450
452
|
```bash
|
|
451
453
|
# Basic approval
|
|
452
454
|
vkit approval:approve 42
|
|
453
455
|
|
|
454
|
-
# With
|
|
456
|
+
# With a shorter TTL and notes
|
|
455
457
|
vkit approval:approve 42 \
|
|
456
|
-
--ttl
|
|
458
|
+
--ttl 1800 \
|
|
457
459
|
--notes "Approved for Q4 analysis. Limited to aggregate data only."
|
|
458
460
|
```
|
|
459
461
|
|
data/lib/vkit/cli/base_cli.rb
CHANGED
|
@@ -71,7 +71,7 @@ module Vkit
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
desc "approval:approve ID", "Approve a pending request"
|
|
74
|
-
option :ttl, type: :numeric, default:
|
|
74
|
+
option :ttl, type: :numeric, desc: "Grant lifetime in seconds (default and maximum: the policy's TTL)"
|
|
75
75
|
define_method("approval:approve") do |id|
|
|
76
76
|
Commands::ApprovalCommand.new.call_approve(
|
|
77
77
|
id: id,
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
+
require_relative "approval_roles"
|
|
4
5
|
|
|
5
6
|
module Vkit
|
|
6
7
|
module CLI
|
|
7
8
|
module Commands
|
|
8
9
|
class ApprovalCommand < BaseCommand
|
|
9
|
-
DEFAULT_TTL = 3600
|
|
10
|
-
|
|
11
10
|
def call_list(state: "pending")
|
|
12
11
|
with_auth do
|
|
13
12
|
user = credential_store.user
|
|
@@ -28,8 +27,11 @@ module Vkit
|
|
|
28
27
|
puts "🆔 #{r["id"]}"
|
|
29
28
|
puts "📂 Dataset: #{r["dataset"]}"
|
|
30
29
|
puts "📄 Fields: #{Array(r["fields"]).join(', ')}"
|
|
31
|
-
puts "👤 Requester: #{r["requester_email"]}"
|
|
32
|
-
puts "🔐 Required: #{r
|
|
30
|
+
puts "👤 Requester: #{r["requester"] || r["requester_email"]}"
|
|
31
|
+
puts "🔐 Required: #{ApprovalRoles.describe(ApprovalRoles.required_roles(r))}"
|
|
32
|
+
if r["state"] == "pending" && Array(r["approved_roles"]).any?
|
|
33
|
+
puts "⏳ Waiting on: #{ApprovalRoles.describe(ApprovalRoles.outstanding_roles(r))}"
|
|
34
|
+
end
|
|
33
35
|
puts "⚙️ Status: #{r["state"].capitalize}"
|
|
34
36
|
puts "🔑 Grant Ref: #{r["grant_ref"] || 'n/a'}" if r["state"] == "approved"
|
|
35
37
|
puts "💬 Reason: #{r["reason"]}"
|
|
@@ -39,19 +41,29 @@ module Vkit
|
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
# Without ttl_seconds the grant lasts as long as the policy allows; the
|
|
45
|
+
# control plane caps a longer request at the policy's TTL.
|
|
46
|
+
def call_approve(id:, ttl_seconds: nil)
|
|
43
47
|
with_auth do
|
|
44
48
|
user = credential_store.user
|
|
45
49
|
org = user["organization_slug"]
|
|
46
50
|
|
|
51
|
+
body = ttl_seconds.nil? ? {} : { ttl_seconds: ttl_seconds }
|
|
47
52
|
res = authenticated_client.post(
|
|
48
53
|
"/api/v1/orgs/#{org}/approvals/#{id}/approve",
|
|
49
|
-
body:
|
|
54
|
+
body: body
|
|
50
55
|
)
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
if res["status"] == "pending"
|
|
58
|
+
puts "✍️ Signed off on request #{id}"
|
|
59
|
+
puts " → Approved by: #{ApprovalRoles.describe(Array(res["approved_roles"]))}"
|
|
60
|
+
puts " → Waiting on: #{ApprovalRoles.describe(Array(res["outstanding_roles"]))}"
|
|
61
|
+
puts " The grant is issued once every role has approved."
|
|
62
|
+
else
|
|
63
|
+
puts "✅ Approved request #{id}"
|
|
64
|
+
puts " → Grant Ref: #{res["grant_ref"] || res["grant_id"]}"
|
|
65
|
+
puts " → Expires: #{res["expires_at"]}"
|
|
66
|
+
end
|
|
55
67
|
end
|
|
56
68
|
end
|
|
57
69
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Vkit
|
|
4
|
+
module CLI
|
|
5
|
+
module Commands
|
|
6
|
+
# Approver roles as the control plane reports them. A request can need a
|
|
7
|
+
# sign-off from several roles (approver_roles); outstanding_roles are the
|
|
8
|
+
# ones still missing. Older control planes send only approver_role.
|
|
9
|
+
module ApprovalRoles
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def required_roles(approval)
|
|
13
|
+
roles = Array(approval["approver_roles"])
|
|
14
|
+
return roles if roles.any?
|
|
15
|
+
|
|
16
|
+
approval["approver_role"].to_s.split(",").map(&:strip).reject(&:empty?)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def outstanding_roles(approval)
|
|
20
|
+
return Array(approval["outstanding_roles"]) if approval.key?("outstanding_roles")
|
|
21
|
+
|
|
22
|
+
approval["state"].to_s == "pending" ? required_roles(approval) : []
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def describe(roles, fallback: "n/a")
|
|
26
|
+
roles.empty? ? fallback : roles.join(", ")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
4
|
require "time"
|
|
5
|
+
require_relative "approval_roles"
|
|
5
6
|
|
|
6
7
|
module Vkit
|
|
7
8
|
module CLI
|
|
@@ -99,6 +100,8 @@ module Vkit
|
|
|
99
100
|
fields: a["fields"],
|
|
100
101
|
requester: a["requester"],
|
|
101
102
|
approver_role: a["approver_role"],
|
|
103
|
+
approver_roles: ApprovalRoles.required_roles(a),
|
|
104
|
+
outstanding_roles: ApprovalRoles.outstanding_roles(a),
|
|
102
105
|
created_at: a["created_at"]
|
|
103
106
|
}
|
|
104
107
|
end
|
|
@@ -110,7 +113,10 @@ module Vkit
|
|
|
110
113
|
puts "Dataset: #{a["dataset"]}"
|
|
111
114
|
puts "Fields: #{Array(a["fields"]).join(", ")}"
|
|
112
115
|
puts "Requester: #{a["requester"]}"
|
|
113
|
-
puts "Role Req: #{a
|
|
116
|
+
puts "Role Req: #{ApprovalRoles.describe(ApprovalRoles.required_roles(a), fallback: "any")}"
|
|
117
|
+
if Array(a["approved_roles"]).any?
|
|
118
|
+
puts "Waiting: #{ApprovalRoles.describe(ApprovalRoles.outstanding_roles(a))}"
|
|
119
|
+
end
|
|
114
120
|
puts "Created: #{format_time(a["created_at"])}"
|
|
115
121
|
puts
|
|
116
122
|
puts "▶ Approve: vkit approval approve #{a["id"]}"
|
|
@@ -75,6 +75,10 @@ module Vkit
|
|
|
75
75
|
token: body["token"],
|
|
76
76
|
user: body["user"]
|
|
77
77
|
}
|
|
78
|
+
when 403
|
|
79
|
+
# The browser sign-in was rejected (e.g. not invited, email not
|
|
80
|
+
# verified); the control plane returns the reason.
|
|
81
|
+
raise login_rejection_message(res)
|
|
78
82
|
when 410
|
|
79
83
|
raise "Login session expired"
|
|
80
84
|
when 404
|
|
@@ -85,6 +89,13 @@ module Vkit
|
|
|
85
89
|
end
|
|
86
90
|
end
|
|
87
91
|
|
|
92
|
+
def login_rejection_message(res)
|
|
93
|
+
body = JSON.parse(res.body.to_s)
|
|
94
|
+
body["message"] || body["error"] || "Sign-in was rejected"
|
|
95
|
+
rescue JSON::ParserError
|
|
96
|
+
"Sign-in was rejected"
|
|
97
|
+
end
|
|
98
|
+
|
|
88
99
|
def password_flow(client)
|
|
89
100
|
email = @email || prompt("Email")
|
|
90
101
|
password = prompt_password("Password")
|
data/lib/vkit/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vaultkit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nnamdi Ogundu
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: thor
|
|
@@ -58,6 +58,7 @@ files:
|
|
|
58
58
|
- lib/vkit/cli/commands/agent_tokens_list_command.rb
|
|
59
59
|
- lib/vkit/cli/commands/agent_tokens_revoke_command.rb
|
|
60
60
|
- lib/vkit/cli/commands/approval_command.rb
|
|
61
|
+
- lib/vkit/cli/commands/approval_roles.rb
|
|
61
62
|
- lib/vkit/cli/commands/approval_watch_command.rb
|
|
62
63
|
- lib/vkit/cli/commands/base_command.rb
|
|
63
64
|
- lib/vkit/cli/commands/datasource_command.rb
|
|
@@ -139,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
139
140
|
- !ruby/object:Gem::Version
|
|
140
141
|
version: '0'
|
|
141
142
|
requirements: []
|
|
142
|
-
rubygems_version: 3.
|
|
143
|
+
rubygems_version: 3.5.22
|
|
143
144
|
signing_key:
|
|
144
145
|
specification_version: 4
|
|
145
146
|
summary: VaultKit CLI
|