seira 0.7.5 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06e2e516ae84d1bcdc4f3320eeb13c83dc6cd162bfbe5e249b53e2b3af74885c
4
- data.tar.gz: 027a214ded3ab47b25fe29b9e8943bd268fe908ff9aa87993ffa07e9c395e350
3
+ metadata.gz: eb319292b2073d2caa5a7d526f70b7f6a707dfa8a7e8b7eba014d488c1ce50ee
4
+ data.tar.gz: b6dfc7dd336518acc1d510177d8eff2f02252351cece68e57c68d9019272d674
5
5
  SHA512:
6
- metadata.gz: f6cc9ea8137d0ae4578a5fbdbeac88f8e8d01916dd8e64f8dc83d4ac30517fda718ae06d0d02b5c354e9d80e3ee3ab3f75df433dda45ac85b60e512cc878b058
7
- data.tar.gz: 828524836a6abc488bc29a3333733887e57b39351f9d54b8ecb9986c49520abd6e8564b97425f702fed90b2256f68c558303c76ee6be49fc58362a3898fc4f32
6
+ metadata.gz: 137620c27df4b7fb22580bb33249d8c6ea6b087f2203205b73f844eef456b20342af2f9c753264439e390ec9c82ad1e47dcda719885cd57ba2a980dbe9803ad9
7
+ data.tar.gz: f40b95e33ab48142deb3673b804507f7f9bf91e37b7a66827e92feb5afbdfaadf59032d6ea3d1848be956037037cd2f4e5d9910a8b442e0b86d34ff2a7b58cfe
data/lib/seira/cluster.rb CHANGED
@@ -41,8 +41,26 @@ module Seira
41
41
  cluster_metadata = settings.clusters[target_cluster]
42
42
 
43
43
  puts("Switching to gcloud config of '#{target_cluster}' and kubernetes cluster of '#{cluster_metadata['cluster']}'") if verbose
44
- exit(1) unless system("gcloud config configurations activate #{target_cluster}")
45
- exit(1) unless system("kubectl config use-context #{cluster_metadata['cluster']}")
44
+ unless system("gcloud config configurations activate #{target_cluster}")
45
+ puts("Try running `seira setup #{target_cluster}` if you have not yet configured this cluster.")
46
+ exit(1)
47
+ end
48
+
49
+ if settings.use_teleport?(target_cluster)
50
+ teleport_status = Seira::Teleport::Status.new
51
+
52
+ unless teleport_status.is_valid?
53
+ if teleport_status.active_cluster == settings.teleport_cluster(target_cluster)
54
+ exit(1) unless system("tsh login")
55
+ else
56
+ exit(1) unless system("tsh login --proxy=#{settings.teleport_cluster(target_cluster)}:443 --auth=#{settings.teleport_auth(target_cluster)}")
57
+ end
58
+ end
59
+
60
+ exit(1) unless system("tsh kube login #{settings.teleport_kubernetes_cluster(target_cluster)}")
61
+ else
62
+ exit(1) unless system("kubectl config use-context #{cluster_metadata['cluster']}")
63
+ end
46
64
 
47
65
  # If we haven't exited by now, it was successful
48
66
  true
@@ -0,0 +1,28 @@
1
+ module Seira
2
+ module Commands
3
+ class Teleport
4
+ attr_reader :context, :command
5
+
6
+ def initialize(command, context: nil)
7
+ @command = command
8
+ @context = context
9
+ end
10
+
11
+ def invoke(clean_output: false, return_output: false)
12
+ puts "Calling: #{calculated_command.green}" unless clean_output
13
+
14
+ if return_output
15
+ `#{calculated_command}`
16
+ else
17
+ system(calculated_command)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def calculated_command
24
+ @calculated_command ||= "tsh #{command}"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,6 @@
1
1
  require 'seira/commands/kubectl'
2
2
  require 'seira/commands/gcloud'
3
+ require 'seira/commands/teleport'
3
4
 
4
5
  module Seira
5
6
  module Commands
@@ -18,5 +19,13 @@ module Seira
18
19
  def self.gcloud(command, context:, clean_output: false, format: :boolean)
19
20
  Gcloud.new(command, context: context, clean_output: clean_output, format: format).invoke
20
21
  end
22
+
23
+ def tsh(command, context:, clean_output: false, return_output: false)
24
+ Seira::Commands.tsh(command, context: context, clean_output: clean_output, return_output: return_output)
25
+ end
26
+
27
+ def self.tsh(command, context:, clean_output: false, return_output: false)
28
+ Teleport.new(command, context: context).invoke(clean_output: clean_output, return_output: return_output)
29
+ end
21
30
  end
22
31
  end
data/lib/seira/pods.rb CHANGED
@@ -41,7 +41,12 @@ module Seira
41
41
  def run_help
42
42
  puts SUMMARY
43
43
  puts "\n\n"
44
- puts "TODO"
44
+ puts "Possible actions:\n\n"
45
+ puts "list: List all the pods (output mode wide)."
46
+ puts "delete: Delete the pod (positional arg)."
47
+ puts "logs: Log the output of the pod (provided via positional arg)."
48
+ puts "top: Print the current resource usage for the specified pod (optional positional arg) or all the pods (default) in the context's namespace."
49
+ puts "connect: Connect to, or run a command on (--command=), a running pod (positional arg or --pod=), or create a new dedicated pod (--dedicated). Can override tier (--tier=)"
45
50
  end
46
51
 
47
52
  def run_list
@@ -53,7 +58,7 @@ module Seira
53
58
  end
54
59
 
55
60
  def run_logs
56
- kubectl("logs #{pod_name} -c #{app}")
61
+ kubectl("logs #{pod_name} -c #{app}", context: context)
57
62
  end
58
63
 
59
64
  def run_top
@@ -62,7 +67,7 @@ module Seira
62
67
 
63
68
  def run_connect
64
69
  tier = nil
65
- pod_name = nil
70
+ pod_name = pod_name
66
71
  dedicated = false
67
72
  command = 'sh'
68
73
 
@@ -68,6 +68,32 @@ module Seira
68
68
  settings['seira']['expected_environment_variable_during_deploys']
69
69
  end
70
70
 
71
+ def use_teleport?(cluster)
72
+ teleport_enabled = settings['seira']['clusters'][cluster].dig('teleport', 'enabled')
73
+
74
+ return false if teleport_enabled.nil?
75
+
76
+ teleport_enabled || ENV['SEIRA_TELEPORT_ENABLED'] == 'true'
77
+ end
78
+
79
+ def teleport_cluster(cluster)
80
+ settings['seira']['clusters'][cluster].dig('teleport', 'cluster')
81
+ end
82
+
83
+ def teleport_auth(cluster)
84
+ settings['seira']['clusters'][cluster].dig('teleport', 'auth')
85
+ end
86
+
87
+ def teleport_kubernetes_cluster(cluster)
88
+ settings['seira']['clusters'][cluster].dig('teleport', 'kubernetes_cluster') || cluster
89
+ end
90
+
91
+ def teleport_role_requirements(cluster)
92
+ requirements = settings['seira']['clusters'][cluster].dig('teleport', 'role_requirements') || []
93
+
94
+ requirements.map { |r| Seira::Teleport::RoleRequirement.new(r) }
95
+ end
96
+
71
97
  private
72
98
 
73
99
  def parse_settings
data/lib/seira/setup.rb CHANGED
@@ -121,6 +121,11 @@ module Seira
121
121
  puts "Installing kubectl..."
122
122
  system('gcloud components install kubectl')
123
123
  end
124
+
125
+ puts "Making sure tsh is installed..."
126
+ unless system('tsh version &> /dev/null')
127
+ puts "Go to https://goteleport.com/docs/installation/ to install tsh.".yellow
128
+ end
124
129
  end
125
130
 
126
131
  def run_status
@@ -0,0 +1,31 @@
1
+ module Seira
2
+ module Teleport
3
+ class Request
4
+ def initialize(role, reviewer: nil, context: nil)
5
+ @role = role
6
+ @reviewer = reviewer
7
+ @context = context
8
+ end
9
+
10
+ def invoke
11
+ command.invoke
12
+ end
13
+
14
+ def cmd
15
+ cmd = "request create --roles '#{@role}'"
16
+ cmd += " --reason '#{reason}'"
17
+ cmd += " --reviewers #{@reviewer}" unless @reviewer.nil?
18
+
19
+ cmd
20
+ end
21
+
22
+ def reason
23
+ "Running: seira #{@context[:cluster]} #{@context[:app]} #{@context[:category]} #{@context[:action]}"
24
+ end
25
+
26
+ def command
27
+ @command ||= Seira::Commands::Teleport.new(cmd, context: @context)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ module Seira
2
+ module Teleport
3
+ class RoleRequirement
4
+ include Comparable
5
+
6
+ attr_reader :commands, :category, :role
7
+
8
+ def initialize(requirement)
9
+ @requirement = requirement
10
+ @category = requirement['category']
11
+ @commands = requirement['commands']
12
+ @role = requirement['role']
13
+ end
14
+
15
+ def matches?(category, command)
16
+ @category == category && command_matches?(command)
17
+ end
18
+
19
+ def <=>(other)
20
+ raise ArgumentError, 'Cannot compare different categories' if category != other.category
21
+
22
+ if commands.nil?
23
+ return -1
24
+ elsif other.commands.nil?
25
+ return 1
26
+ end
27
+
28
+ commands.length <=> other.commands.length
29
+ end
30
+
31
+ private
32
+
33
+ def command_matches?(command)
34
+ return false if command == 'help'
35
+ return true if @requirement['commands'].nil?
36
+
37
+ @requirement['commands'].include?(command)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,58 @@
1
+ require 'json'
2
+ require 'date'
3
+ require 'seira/commands/teleport'
4
+
5
+ module Seira
6
+ module Teleport
7
+ class Status
8
+ attr_reader :data
9
+
10
+ def initialize(data: nil)
11
+ @data = data
12
+ @data ||= get_status_json
13
+ end
14
+
15
+ def [](key)
16
+ data[key]
17
+ end
18
+
19
+ def active_cluster
20
+ data.dig('active', 'cluster')
21
+ end
22
+
23
+ def kubernetes_cluster
24
+ data.dig('active','kubernetes_cluster')
25
+ end
26
+
27
+ def roles
28
+ @roles ||= data.dig('active', 'roles')
29
+ end
30
+
31
+ def has_role?(role)
32
+ return false if roles.nil?
33
+
34
+ roles.include?(role)
35
+ end
36
+
37
+ def is_valid?
38
+ valid_until = data.dig('active', 'valid_until')
39
+ return false if valid_until.nil?
40
+
41
+ DateTime.parse(data.dig('active', 'valid_until')) > DateTime.now
42
+ end
43
+
44
+ private
45
+
46
+ def get_status_json
47
+ cmd = Seira::Commands::Teleport.new('status -f json', context: :none)
48
+
49
+ out = cmd.invoke(clean_output: true, return_output: true)
50
+ if out == ''
51
+ {}
52
+ else
53
+ JSON.parse(cmd.invoke(clean_output: true, return_output: true))
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ require 'seira/teleport/status'
2
+ require 'seira/teleport/role_requirements'
3
+ require 'seira/teleport/request'
data/lib/seira/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Seira
2
- VERSION = "0.7.5".freeze
2
+ VERSION = "0.8.1".freeze
3
3
  end
data/lib/seira.rb CHANGED
@@ -20,6 +20,7 @@ require 'seira/settings'
20
20
  require 'seira/setup'
21
21
  require 'seira/node_pools'
22
22
  require 'seira/util/resource_renderer'
23
+ require 'seira/teleport'
23
24
 
24
25
  # A base runner class that does base checks and then delegates the actual
25
26
  # work for the command to a class in lib/seira folder.
@@ -118,6 +119,16 @@ module Seira
118
119
  exit(1)
119
120
  end
120
121
 
122
+ if settings.use_teleport?(cluster)
123
+ role_requirements = settings.teleport_role_requirements(cluster)
124
+ required_role = role_requirements.filter { |rr| rr.matches?(category, action) }.sort.first&.role
125
+ status = Seira::Teleport::Status.new
126
+
127
+ unless required_role.nil? || status.has_role?(required_role)
128
+ Seira::Teleport::Request.new(required_role, reviewer: ENV['TELEPORT_REVIEWER'], context: passed_context).invoke
129
+ end
130
+ end
131
+
121
132
  if category == 'cluster'
122
133
  perform_action_validation(klass: command_class, action: action)
123
134
  command_class.new(action: action, args: args, context: passed_context, settings: settings).run
@@ -142,6 +153,7 @@ module Seira
142
153
  region: settings.region_for_cluster(cluster),
143
154
  zone: settings.zone_for_cluster(cluster),
144
155
  app: app,
156
+ category: category,
145
157
  action: action,
146
158
  args: args
147
159
  }
@@ -159,6 +171,11 @@ module Seira
159
171
  exit(1)
160
172
  end
161
173
 
174
+ unless system("tsh version > /dev/null 2>&1")
175
+ puts "Teleport CLI not installed properly. Please install `tsh` before using seira.".red
176
+ exit(1)
177
+ end
178
+
162
179
  # The first arg must always be the cluster. This ensures commands are not run by
163
180
  # accident on the wrong kubernetes cluster or gcloud project.
164
181
  exit(1) unless Seira::Cluster.new(action: nil, args: nil, context: nil, settings: settings).switch(target_cluster: cluster, verbose: false)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seira
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Ringwelski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-28 00:00:00.000000000 Z
11
+ date: 2023-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline
@@ -123,6 +123,7 @@ files:
123
123
  - lib/seira/commands.rb
124
124
  - lib/seira/commands/gcloud.rb
125
125
  - lib/seira/commands/kubectl.rb
126
+ - lib/seira/commands/teleport.rb
126
127
  - lib/seira/config.rb
127
128
  - lib/seira/db.rb
128
129
  - lib/seira/db/create.rb
@@ -135,6 +136,10 @@ files:
135
136
  - lib/seira/secrets.rb
136
137
  - lib/seira/settings.rb
137
138
  - lib/seira/setup.rb
139
+ - lib/seira/teleport.rb
140
+ - lib/seira/teleport/request.rb
141
+ - lib/seira/teleport/role_requirements.rb
142
+ - lib/seira/teleport/status.rb
138
143
  - lib/seira/util/resource_renderer.rb
139
144
  - lib/seira/version.rb
140
145
  - resources/adjectives.txt