lib/conjur/policy/yaml/handler.rb in conjur-asset-policy-0.12.0 vs lib/conjur/policy/yaml/handler.rb in conjur-asset-policy-0.13.0
- old
+ new
@@ -10,21 +10,17 @@
# its particular context (sequence, mapping, etc).
#
# The handler can decide that the message is not allowed by not implementing the message.
#
class Base
- attr_reader :parent
+ attr_reader :parent, :anchor
- def initialize parent
+ def initialize parent, anchor
@parent = parent
+ @anchor = anchor
end
- # Each handler should implement this method to return the result object (which may only be
- # partially constructed). This method is used by the root handler to associate the handler
- # result with an anchor (if applicable).
- def result; raise "Not implemented"; end
-
# Handlers are organized in a stack. Each handler can find the root Handler by traversing up the stack.
def handler
parent.handler
end
@@ -43,17 +39,17 @@
raise "Unexpected alias #{anchor}"
end
# Start a new mapping with the specified tag.
# If the handler wants to accept the message, it should return a new handler.
- def start_mapping tag
+ def start_mapping tag, anchor
raise "Unexpected mapping"
end
# Start a new sequence.
# If the handler wants to accept the message, it should return a new handler.
- def start_sequence
+ def start_sequence anchor
raise "Unexpected sequence"
end
# End the current sequence. The handler should populate the sequence into the parent handler.
def end_sequence
@@ -64,13 +60,11 @@
def end_mapping
raise "Unexpected end of mapping"
end
# Process a scalar value. It may be a map key, a map value, or a sequence value.
- # The handler should return a result from this method, so that the root Handler can
- # associate it with an anchor, if any.
- def scalar value, tag, quoted
+ def scalar value, tag, quoted, anchor
raise "Unexpected scalar"
end
protected
@@ -101,11 +95,11 @@
# Handles the root document, which should be a sequence.
class Root < Base
attr_reader :result, :handler
def initialize handler
- super nil
+ super nil, nil
@handler = handler
@result = nil
end
@@ -117,14 +111,14 @@
end
# The document root is expected to start with a sequence.
# A Sequence handler is constructed with no implicit type. This
# sub-handler handles the message.
- def start_sequence
- Sequence.new(self, nil).tap do |h|
+ def start_sequence anchor
+ Sequence.new(self, anchor, nil).tap do |h|
h.push_handler
- end.result
+ end
end
# Finish the sequence, and the document.
def end_sequence
pop_handler
@@ -135,84 +129,87 @@
# +record_type+ default record type, inferred from the field name on the parent record.
# +args+ the start_sequence arguments.
class Sequence < Base
attr_reader :record_type
- def initialize parent, record_type
- super parent
+ def initialize parent, anchor, record_type
+ super parent, anchor
@record_type = record_type
@list = []
end
- def result; @list; end
-
# Adds a mapping to the sequence.
def mapping value
+ handler.log { "#{handler.indent}Adding mapping #{value} to sequence" }
@list.push value
end
# Adds a sequence to the sequence.
def sequence value
+ handler.log { "#{handler.indent}Adding sequence #{value} to sequence" }
@list.push value
end
# When the sequence receives an alias, the alias should be mapped to the previously stored
# value and added to the result list.
def alias anchor
+ handler.log { "#{handler.indent}Adding alias *#{anchor} to sequence, whose value is #{handler.anchor(anchor)}" }
@list.push handler.anchor(anchor)
end
# When the sequence contains a mapping, a new record should be created corresponding to either:
#
# * The explicit stated type (tag) of the mapping
# * The implicit field type of the sequence
#
# If neither of these is available, it's an error.
- def start_mapping tag
+ def start_mapping tag, anchor
if type = type_of(tag, record_type)
- Mapping.new(self, type).tap do |h|
+ Mapping.new(self, anchor, type).tap do |h|
h.push_handler
- end.result
+ end
else
raise "No type given or inferred for sequence entry"
end
end
# Process a sequence within a sequence.
- def start_sequence
- Sequence.new(self, record_type).tap do |h|
+ def start_sequence anchor
+ Sequence.new(self, anchor, record_type).tap do |h|
h.push_handler
- end.result
+ end
end
# When the sequence contains a scalar, the value should be appended to the result.
- def scalar value, tag, quoted
+ def scalar value, tag, quoted, anchor
scalar_value(value, tag, quoted, record_type).tap do |value|
+ handler.log { "#{handler.indent}Adding scalar *#{value} to sequence" }
@list.push value
+ handler.anchor anchor, value if anchor
end
end
def end_sequence
parent.sequence @list
+ handler.anchor anchor, @list if anchor
pop_handler
end
end
# Handles a mapping, each of which will be parsed into a structured record.
class Mapping < Base
attr_reader :type
- def initialize parent, type
- super parent
+ def initialize parent, anchor, type
+ super parent, anchor
@record = type.new
end
- def result; @record; end
-
def map_entry key, value
+ handler.log { "#{handler.indent}Setting map entry #{key} = #{value}" }
if @record.respond_to?(:[]=)
@record.send(:[]=, key, value)
else
begin
@record.send("#{key}=", value)
@@ -223,80 +220,80 @@
end
# Begins a mapping with the anchor value as the key.
def alias anchor
key = handler.anchor(anchor)
- MapEntry.new(self, @record, key).tap do |h|
+ MapEntry.new(self, nil, @record, key).tap do |h|
h.push_handler
- end.result
+ end
end
# Begins a new map entry.
- def scalar value, tag, quoted
+ def scalar value, tag, quoted, anchor
value = scalar_value(value, tag, quoted, type)
- MapEntry.new(self, @record, value).tap do |h|
+ MapEntry.new(self, anchor, @record, value).tap do |h|
h.push_handler
- end.result
+ end
end
def end_mapping
parent.mapping @record
+ handler.anchor anchor, @record if anchor
pop_handler
end
end
# Processes a map entry. At this point, the parent record and the map key are known.
class MapEntry < Base
attr_reader :record, :key
- def initialize parent, record, key
- super parent
+ def initialize parent, anchor, record, key
+ super parent, anchor
@record = record
@key = key
end
- def result; nil; end
-
def sequence value
value value
end
def mapping value
value value
end
def value value
parent.map_entry @key, value
+ handler.anchor anchor, value if anchor
pop_handler
end
# Interpret the alias as the map value and populate in the parent.
def alias anchor
value handler.anchor(anchor)
end
# Start a mapping as a map value.
- def start_mapping tag
+ def start_mapping tag, anchor
if type = type_of(tag, yaml_field_type(key))
- Mapping.new(self, type).tap do |h|
+ Mapping.new(self, anchor, type).tap do |h|
h.push_handler
- end.result
+ end
else
# We got a mapping on a simple type
raise "Attribute '#{key}' can't be a mapping"
end
end
# Start a sequence as a map value.
- def start_sequence
- Sequence.new(self, yaml_field_type(key)).tap do |h|
+ def start_sequence anchor
+ Sequence.new(self, anchor, yaml_field_type(key)).tap do |h|
h.push_handler
- end.result
+ end
end
- def scalar value, tag, quoted
+ def scalar value, tag, quoted, anchor
value scalar_value(value, tag, quoted, yaml_field_type(key))
end
protected
@@ -310,13 +307,17 @@
@handlers = [ @root ]
@anchors = {}
@filename = "<no-filename>"
end
+ def result
+ @root.result
+ end
+
def push_handler handler
- log {"#{indent}pushing handler #{handler.class}"}
@handlers.push handler
+ log {"#{indent}pushed handler #{handler.class}"}
end
def pop_handler
@handlers.pop
log {"#{indent}popped to handler #{handler.class}"}
@@ -336,32 +337,29 @@
else
nil
end
end
- def result; @root.result; end
-
def handler; @handlers.last; end
def alias key
+ log {"#{indent}WARNING: anchor '#{key}' is not defined"} unless anchor(key)
log {"#{indent}anchor '#{key}'=#{anchor(key)}"}
handler.alias key
end
def start_mapping *args
log {"#{indent}start mapping #{args}"}
anchor, tag, _ = args
tag = "!automatic-role" if %w(!managed-role !managed_role).include?(tag)
- value = handler.start_mapping tag
- anchor anchor, value
+ handler.start_mapping tag, anchor
end
def start_sequence *args
log {"#{indent}start sequence : #{args}"}
anchor, _ = args
- value = handler.start_sequence
- anchor anchor, value
+ handler.start_sequence anchor
end
def end_sequence
log {"#{indent}end sequence"}
handler.end_sequence
@@ -374,11 +372,10 @@
def scalar *args
# value, anchor, tag, plain, quoted, style
value, anchor, tag, _, quoted = args
log {"#{indent}got scalar #{tag ? tag + '=' : ''}#{value}#{anchor ? '#' + anchor : ''}"}
- value = handler.scalar value, tag, quoted
- anchor anchor, value
+ handler.scalar value, tag, quoted, anchor
end
def log &block
logger.debug('conjur/policy/handler') {
yield
\ No newline at end of file