1
+ #!/opt/puppetlabs/puppet/bin/ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'json'
5
+ require 'net/https'
6
+ require 'puppet'
7
+
8
+ # UpdatePeMasterRules task class
9
+ class UpdatePeMasterRules
10
+ def initialize ( params )
11
+ @params = params
12
+ end
13
+
14
+ def https_client
15
+ client = Net ::HTTP . new ( Puppet . settings [ :certname ] , 4433 )
16
+ client . use_ssl = true
17
+ client . cert = @cert ||= OpenSSL ::X509 ::Certificate . new ( File . read ( Puppet . settings [ :hostcert ] ) )
18
+ client . key = @key ||= OpenSSL ::PKey ::RSA . new ( File . read ( Puppet . settings [ :hostprivkey ] ) )
19
+ client . verify_mode = OpenSSL ::SSL ::VERIFY_PEER
20
+ client . ca_file = Puppet . settings [ :localcacert ]
21
+ client
22
+ end
23
+
24
+ def get_pe_master_group_id
25
+ net = https_client
26
+ res = net . get ( '/classifier-api/v1/groups' )
27
+
28
+ unless res . code == '200'
29
+ raise "Failed to fetch groups: HTTP #{ res . code } - #{ res . body } "
30
+ end
31
+
32
+ groups = JSON . parse ( res . body )
33
+ pe_master_group = groups . find { |group | group [ 'name' ] == 'PE Master' }
34
+
35
+ raise "Could not find PE Master group" unless pe_master_group
36
+ pe_master_group [ 'id' ]
37
+ rescue JSON ::ParserError => e
38
+ raise "Invalid JSON response from server: #{ e . message } "
39
+ rescue StandardError => e
40
+ raise "Error fetching PE Master group ID: #{ e . message } "
41
+ end
42
+
43
+ def get_current_rules ( group_id )
44
+ net = https_client
45
+ url = "/classifier-api/v1/groups/#{ group_id } /rules"
46
+ req = Net ::HTTP ::Get . new ( url )
47
+ res = net . request ( req )
48
+
49
+ unless res . code == '200'
50
+ raise "Failed to fetch rules: HTTP #{ res . code } - #{ res . body } "
51
+ end
52
+
53
+ JSON . parse ( res . body ) [ 'rule' ]
54
+ rescue JSON ::ParserError => e
55
+ raise "Invalid JSON response from server: #{ e . message } "
56
+ rescue StandardError => e
57
+ raise "Error fetching rules: #{ e . message } "
58
+ end
59
+
60
+ def update_rules ( group_id )
61
+ net = https_client
62
+ begin
63
+ current_rules = get_current_rules ( group_id )
64
+
65
+ # Find the specific "and" rule for pe_compiler and transform it to match any *_compiler role
66
+ old_rule = [ 'and' , [ '=' , [ 'trusted' , 'extensions' , 'pp_auth_role' ] , 'pe_compiler' ] ]
67
+ new_rule = [ 'and' , [ '~' , [ 'trusted' , 'extensions' , 'pp_auth_role' ] , '.*_compiler$' ] ]
68
+
69
+ # Replace the old rule with the new rule if it exists
70
+ new_rules = current_rules . map { |rule | rule == old_rule ? new_rule : rule }
71
+
72
+ # Update the group with the modified rules
73
+ url = "/classifier-api/v1/groups/#{ group_id } "
74
+ req = Net ::HTTP ::Post . new ( url )
75
+ req [ 'Content-Type' ] = 'application/json'
76
+ req . body = { rule : new_rules } . to_json
77
+
78
+ res = net . request ( req )
79
+
80
+ case res . code
81
+ when '200' , '201' , '204'
82
+ puts "Successfully transformed pe_compiler rule to match any *_compiler role in group #{ group_id } "
83
+ else
84
+ begin
85
+ error_body = JSON . parse ( res . body . to_s )
86
+ raise "Failed to update rules: #{ error_body [ 'kind' ] || error_body } "
87
+ rescue JSON ::ParserError
88
+ raise "Invalid response from server (status #{ res . code } ): #{ res . body } "
89
+ end
90
+ end
91
+ rescue StandardError => e
92
+ raise "Error during rules update: #{ e . message } "
93
+ end
94
+ end
95
+
96
+ def execute!
97
+ group_id = get_pe_master_group_id
98
+ update_rules ( group_id )
99
+ end
100
+ end
101
+
102
+ # Run the task unless an environment flag has been set
103
+ unless ENV [ 'RSPEC_UNIT_TEST_MODE' ]
104
+ Puppet . initialize_settings
105
+ task = UpdatePeMasterRules . new ( JSON . parse ( STDIN . read ) )
106
+ task . execute!
107
+ end
0 commit comments