Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support access: security policies on Explore and Canvas resources #5728

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
386 changes: 200 additions & 186 deletions proto/gen/rill/runtime/v1/resources.pb.go

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions proto/gen/rill/runtime/v1/resources.pb.validate.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions proto/gen/rill/runtime/v1/runtime.swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3385,6 +3385,11 @@ definitions:
items:
type: object
$ref: '#/definitions/v1CanvasItem'
securityRules:
type: array
items:
type: object
$ref: '#/definitions/v1SecurityRule'
v1CanvasState:
type: object
properties:
Expand Down
1 change: 1 addition & 0 deletions proto/rill/runtime/v1/resources.proto
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ message CanvasSpec {
uint32 gap = 3;
repeated ComponentVariable variables = 5;
repeated CanvasItem items = 4;
repeated SecurityRule security_rules = 6;
begelundmuller marked this conversation as resolved.
Show resolved Hide resolved
}

message CanvasState {
Expand Down
13 changes: 13 additions & 0 deletions runtime/compilers/rillv1/parse_canvas.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type CanvasYAML struct {
Width *uint32 `yaml:"width"`
Height *uint32 `yaml:"height"`
} `yaml:"items"`
Security *SecurityPolicyYAML `yaml:"security"`
}

func (p *Parser) parseCanvas(node *Node) error {
Expand Down Expand Up @@ -80,6 +81,17 @@ func (p *Parser) parseCanvas(node *Node) error {
node.Refs = append(node.Refs, ResourceName{Kind: ResourceKindComponent, Name: component})
}

// Parse security rules
rules, err := tmp.Security.Proto()
if err != nil {
return err
}
for _, rule := range rules {
if rule.GetAccess() == nil {
return fmt.Errorf("the 'canvas' resource type only supports 'access' security rules")
}
}

// Track canvas
r, err := p.insertResource(ResourceKindCanvas, node.Name, node.Paths, node.Refs...)
if err != nil {
Expand All @@ -92,6 +104,7 @@ func (p *Parser) parseCanvas(node *Node) error {
r.CanvasSpec.Gap = tmp.Gap
r.CanvasSpec.Variables = variables
r.CanvasSpec.Items = items
r.CanvasSpec.SecurityRules = rules

// Track inline components
for _, def := range inlineComponentDefs {
Expand Down
13 changes: 13 additions & 0 deletions runtime/compilers/rillv1/parse_explore.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type ExploreYAML struct {
ComparisonMode string `yaml:"comparison_mode"`
ComparisonDimension string `yaml:"comparison_dimension"`
} `yaml:"presets"`
Security *SecurityPolicyYAML `yaml:"security"`
}

// NamesYAML parses a list of names with support for a '*' scalar for all names,
Expand Down Expand Up @@ -268,6 +269,17 @@ func (p *Parser) parseExplore(node *Node) error {
})
}

// Build security rules
rules, err := tmp.Security.Proto()
if err != nil {
return err
}
for _, rule := range rules {
if rule.GetAccess() == nil {
return fmt.Errorf("the 'explore' resource type only supports 'access' security rules")
}
}

// Track explore
r, err := p.insertResource(ResourceKindExplore, node.Name, node.Paths, node.Refs...)
if err != nil {
Expand All @@ -286,6 +298,7 @@ func (p *Parser) parseExplore(node *Node) error {
r.ExploreSpec.TimeRanges = timeRanges
r.ExploreSpec.TimeZones = tmp.TimeZones
r.ExploreSpec.Presets = presets
r.ExploreSpec.SecurityRules = rules

return nil
}
12 changes: 6 additions & 6 deletions runtime/compilers/rillv1/parse_metrics_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type MetricsViewYAML struct {
Ignore bool `yaml:"ignore"` // Deprecated
ValidPercentOfTotal bool `yaml:"valid_percent_of_total"`
}
Security *MetricsViewSecurityPolicyYAML
Security *SecurityPolicyYAML

// DEPRECATED FIELDS
DefaultTimeRange string `yaml:"default_time_range"`
Expand Down Expand Up @@ -191,7 +191,7 @@ func (f *MetricsViewMeasureWindow) UnmarshalYAML(v *yaml.Node) error {
return nil
}

type MetricsViewSecurityPolicyYAML struct {
type SecurityPolicyYAML struct {
Access string `yaml:"access"`
RowFilter string `yaml:"row_filter"`
Include []*struct {
Expand All @@ -202,10 +202,10 @@ type MetricsViewSecurityPolicyYAML struct {
Condition string `yaml:"if"`
Names yaml.Node // []string or "*" (will be parsed with parseNamesYAML)
}
Rules []*MetricsViewSecurityRuleYAML `yaml:"rules"`
Rules []*SecurityRuleYAML `yaml:"rules"`
}

func (p *MetricsViewSecurityPolicyYAML) Proto() ([]*runtimev1.SecurityRule, error) {
func (p *SecurityPolicyYAML) Proto() ([]*runtimev1.SecurityRule, error) {
var rules []*runtimev1.SecurityRule
if p == nil {
return rules, nil
Expand Down Expand Up @@ -355,7 +355,7 @@ func (p *MetricsViewSecurityPolicyYAML) Proto() ([]*runtimev1.SecurityRule, erro
return rules, nil
}

type MetricsViewSecurityRuleYAML struct {
type SecurityRuleYAML struct {
Type string
Action string
If string
Expand All @@ -364,7 +364,7 @@ type MetricsViewSecurityRuleYAML struct {
SQL string
}

func (r *MetricsViewSecurityRuleYAML) Proto() (*runtimev1.SecurityRule, error) {
func (r *SecurityRuleYAML) Proto() (*runtimev1.SecurityRule, error) {
condition := r.If
if condition != "" {
tmp, err := ResolveTemplate(condition, validationTemplateData)
Expand Down
12 changes: 10 additions & 2 deletions runtime/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,17 @@ func (p *securityEngine) resolveRules(claims *SecurityClaims, r *runtimev1.Resou
// Everyone can access a component.
case ResourceKindComponent:
rules = append(rules, allowAccessRule)
// Everyone can access a canvas.
// Determine access using the canvas' security rules. If there are none, then everyone can access it.
case ResourceKindCanvas:
rules = append(rules, allowAccessRule)
spec := r.GetCanvas().State.ValidSpec
if spec == nil {
spec = r.GetCanvas().Spec // Not ideal, but better than giving access to the full resource
}
if len(spec.SecurityRules) == 0 {
rules = append(rules, allowAccessRule)
} else {
rules = append(rules, spec.SecurityRules...)
}
// Determine access using the metrics view's security rules. If there are none, then everyone can access it.
case ResourceKindMetricsView:
spec := r.GetMetricsView().State.ValidSpec
Expand Down
6 changes: 6 additions & 0 deletions web-common/src/proto/gen/rill/runtime/v1/resources_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4177,6 +4177,11 @@ export class CanvasSpec extends Message<CanvasSpec> {
*/
items: CanvasItem[] = [];

/**
* @generated from field: repeated rill.runtime.v1.SecurityRule security_rules = 6;
*/
securityRules: SecurityRule[] = [];

constructor(data?: PartialMessage<CanvasSpec>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -4190,6 +4195,7 @@ export class CanvasSpec extends Message<CanvasSpec> {
{ no: 3, name: "gap", kind: "scalar", T: 13 /* ScalarType.UINT32 */ },
{ no: 5, name: "variables", kind: "message", T: ComponentVariable, repeated: true },
{ no: 4, name: "items", kind: "message", T: CanvasItem, repeated: true },
{ no: 6, name: "security_rules", kind: "message", T: SecurityRule, repeated: true },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CanvasSpec {
Expand Down
1 change: 1 addition & 0 deletions web-common/src/runtime-client/gen/index.schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2206,6 +2206,7 @@ export interface V1CanvasSpec {
gap?: number;
variables?: V1ComponentVariable[];
items?: V1CanvasItem[];
securityRules?: V1SecurityRule[];
}

export interface V1CanvasState {
Expand Down
Loading