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