Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Data Class →

Generally Available (Green)

Confidential (Yellow)

Restricted (Red)

Audience

All data access roles (not public)

Dean/Division Leader Role
(Identified data for own unit)

Reporting and Compliance Roles

(University-wide access as needed)

Others must provide justification for use

Identified data

Reporting and Compliance Roles

(University-wide access)

Types of Data

•Name

•Title (fac/staff) / Level (students)

•HR Title (fac/staff)

•Department / Program

•Supervisor

•Campus

•Pronouns (user provided)

•Email address

•Affiliations (faculty/staff/student/...)

•Classification (temp, post doc, RA, staff/grade, faculty)

•Compensation

•Course registrations

•Age range (..., 25-35, 36-45, …)

•Financial transaction data 

•Leave/return dates

•Service dates

•Space assignments

•Grant proposals and awards

•Enrollment status

•Home address

•Local address

•Alum/donor name/contact info

•Citizenship

•Race/ethnicity

•Gender identity

•Religion

•PHI

•Marital status

•Date of birth

•Benefit selections

•Admissions decisions (before release)

•Grades

•Alum/donor gift history

•Social security number

•Driver’s license number

•Passport number

•Visa/Citizenship info

Tags, policies and roles have been added for Confidential and Restricted in the dev environment for testing. Ultimately, roles will exist in Grouper where their membership can be managed.

...

Restricted

VQL

Code Block
CREATE OR REPLACE ROLE confidentialcls_restricted ''
 
GRANT CONNECT, METADATA, EXECUTE ON test
 ;

CREATE OR REPLACE TAG confidential
    DESCRIPTION = 'Used to tag views or columns that fall under the Confidential data definition';
    
ROLE cls_restricted_dob ''
GRANT CONNECT, METADATA, EXECUTE ON test;

CREATE OR REPLACE ROLE cls_restricted_gender ''
GRANT CONNECT, METADATA, EXECUTE ON test;

CREATE OR REPLACE ROLE cls_restricted_race ''
GRANT CONNECT, METADATA, EXECUTE ON test;

CREATE OR REPLACE GLOBAL_SECURITY_POLICY mask_confidential_columnsTAG cls
    DESCRIPTION = 'For non-RLSTags views, masks alland columns withthat thehave confidential tag for non-admins without the confidential role'CLS (column level security) applied';

CREATE OR REPLACE TAG cls_restricted
    ENABLEDDESCRIPTION = 'Tags TRUEcolumns with restricted data that AUDIENCEhave (column-level security (CLS) applied.';

CREATE OR REPLACE TAG NOT_IN ROLES (confidential, "grp_ds_denodo-admin", restricted)
    )
    ELEMENTS (
        VIEWS NOT TAGGED  (rls_dept)cls_restricted_dob
    DESCRIPTION = 'Tags columns with restricted data of birth (DOB) data to have column-level security (CLS) applied';

CREATE OR REPLACE TAG cls_restricted_gender
    )DESCRIPTION = 'Tags columns with RESTRICTIONrestricted (gender data to have column-level security (CLS) applied';
 FILTER = '' 
CREATE OR REPLACE TAG cls_restricted_race
  MASKING ANY (confidential)DESCRIPTION WITH (HIDE) (numbers WITH DEFAULT, datetimes WITH DEFAULT, texts WITH DEFAULT) 
    );

image-20241205-191944.pngImage Removed

image-20241123-003757.pngImage Removed

Restricted

VQL

Code Block
= 'Tags columns with restricted race data to have column-level security (CLS) applied';

CREATE OR REPLACE ROLE restricted ''GLOBAL_SECURITY_POLICY cls_restricted_dob
   GRANT CONNECT,DESCRIPTION METADATA,= EXECUTE'Masks ONall test;columns CREATEwith OR REPLACE TAG restricted
    DESCRIPTION = 'Used to tag views or columns whose data fall under the Restricted definition'
CREATE OR REPLACE GLOBAL_SECURITY_POLICY mask_restricted_columnsthe cls_restricted_dob tag for non-admins without the cls_restricted or cls_restricted_dob role'
    ENABLED = TRUE
    AUDIENCE (
        NOT_IN ROLES (cls_restricted, cls_restricted_dob)
    DESCRIPTION)
= 'For non-RLS views, masksELEMENTS all(
columns with the confidential tag for non-admins without theALL confidentialVIEWS
role'    )
ENABLED = TRUE     AUDIENCERESTRICTION (
        NOT_INFILTER ROLES ("grp_ds_denodo-admin", restricted)= ''
    )    MASKING ELEMENTSANY (cls_restricted_dob) WITH (HIDE) (numbers WITH DEFAULT, datetimes WITH DEFAULT, VIEWStexts NOTWITH TAGGED  (rls_dept)DEFAULT) 
    );

CREATE OR REPLACE RESTRICTION (GLOBAL_SECURITY_POLICY cls_restricted_gender
        FILTERDESCRIPTION = ''Masks all columns with the cls_restricted_gender tag for  MASKING ANY (restricted) WITH (HIDE) (numbers WITH DEFAULT, datetimes WITH DEFAULT, texts WITH DEFAULT) 
    );

...

This can be expanded upon by leveraging user attributes from LDAP/SAML: https://community.denodo.com/kb/en/view/document/How%20to%20implement%20ABAC%20Capabilities%20with%20Global%20Security%20Policies

Row-level Security (RLS)

In addition to column-level security, you can employ row-level security and limit the rows users can see. The VQL below will create policies to hide all rows for all users except ones with the read_test, data_strategy or iam roles.

VQL

Code Block
CREATE OR REPLACE ROLE data_strategy ''
  GRANT CONNECT, METADATA, EXECUTE ON test;
  
CREATE OR REPLACE ROLE iam ''
  GRANT CONNECT, METADATA, EXECUTE ON test;
  
CREATE OR REPLACE ROLE read_test ''
  GRANT CONNECT, METADATA, EXECUTE ON test;
  
CREATE OR REPLACE ROLE general ''
  GRANT CONNECT, METADATA, EXECUTE ON test;
  
CREATE OR REPLACE TAG rls_dept
    DESCRIPTION = 'Used to tag views that should have RLS applied based on department';

CREATE OR REPLACE GLOBAL_SECURITY_POLICY rls_hide_all
    DESCRIPTION = 'Hides all rows for RLS-enabled views'
    ENABLED = TRUE
    AUDIENCE (
        NOT_IN ROLES (data_strategy, iam, read_test)
    )
    ELEMENTS (
        COLUMNS TAGGED ANY (rls_dept)
    )
    RESTRICTION (
        FILTER = '0=1'
        REJECT 
    );


CREATE OR REPLACE GLOBAL_SECURITY_POLICY rls_dept_data_strategy
    DESCRIPTION = 'RLS department policy for data strategy'
    ENABLED = TRUE
    AUDIENCE (
        ANY ROLES (data_strategy)
    )
    ELEMENTS (
        COLUMNS TAGGED ANY (rls_dept)
    )
    RESTRICTION (
        FILTER = 'rls_dept = ''DS'''non-admins without the cls_restricted or cls_restricted_gender role'
    ENABLED = TRUE
    AUDIENCE (
        NOT_IN ROLES (cls_restricted, cls_restricted_gender)
    )
    ELEMENTS (
        ALL  REJECT VIEWS
    );
 CREATE OR REPLACE GLOBAL_SECURITY_POLICY rls_dept_iamRESTRICTION (
    DESCRIPTION = 'RLS department policyFILTER for= data strategy''
    ENABLED = TRUE  MASKING ANY  AUDIENCE(cls_restricted_gender) WITH (HIDE) (numbers WITH DEFAULT, datetimes WITH DEFAULT, texts WITH ANYDEFAULT) ROLES
(iam)
    );

CREATE OR REPLACE ELEMENTS (GLOBAL_SECURITY_POLICY cls_restricted_race
    DESCRIPTION = 'Masks all COLUMNScolumns TAGGEDwith ANY (rls_dept)
    )
    RESTRICTION (
   the cls_restricted_race tag for non-admins without the cls_restricted or cls_restricted_race role'
    FILTERENABLED = 'rls_deptTRUE
= ''IAM'''   AUDIENCE (
     REJECT   NOT_IN ROLES (cls_restricted, cls_restricted_race);

CREATE OR REPLACE GLOBAL_SECURITY_POLICY rls_dept_mask_confidential )
    ELEMENTS DESCRIPTION(
= 'Applies confidential CLS to department-based RLS views' ALL VIEWS
  ENABLED = TRUE)
    AUDIENCERESTRICTION (
        FILTER = NOT_IN''
ROLES (data_strategy, iam)     ) MASKING ANY (cls_restricted_race) WITH ELEMENTS(HIDE) (numbers WITH DEFAULT, datetimes WITH DEFAULT, texts WITH DEFAULT) 
VIEWS TAGGED ANY  (rls_dept);

...

Confidential

VQL

Code Block
CREATE OR REPLACE ROLE )cls_confidential ''
  GRANT RESTRICTIONCONNECT, (METADATA, EXECUTE ON test;
  
CREATE OR FILTERREPLACE = ''TAG cls_confidential
    DESCRIPTION =   MASKING ANY (confidential) WITH (HIDE) (numbers WITH DEFAULT, datetimes WITH DEFAULT, texts WITH DEFAULT) 
    );'Used to tag columns that fall under the Confidential data definition to apply column-level security (CLS)';
    
CREATE OR REPLACE GLOBAL_SECURITY_POLICY rls_dept_mask_restrictedcls_confidential
    DESCRIPTION = 'Applies confidential CLS to department-based RLS viewsMasks all columns with the cls_confidential tag for non-admins without the cls_confidential role'
    ENABLED = TRUE
    AUDIENCE (
        NOT_IN ROLES (iamcls_confidential, cls_restricted)
    )
    ELEMENTS (
        ALL VIEWS
TAGGED ANY  (rls_dept)
    )
    RESTRICTION (
        FILTER = ''
        MASKING ANY (restrictedcls_confidential) WITH (HIDE) (numbers WITH DEFAULT, datetimes WITH DEFAULT, texts WITH DEFAULT) 
(numbers  WITH DEFAULT, datetimes WITH DEFAULT, texts WITH DEFAULT) 
    );

...

This can be expanded upon by leveraging user attributes from LDAP/SAML: https://community.denodo.com/kb/en/view/document/How%20to%20implement%20ABAC%20Capabilities%20with%20Global%20Security%20Policies

Demo

Code Block
CREATE OR REPLACE VIEW cls_test
    FOLDER = '/02-transformation'(
        hire_dt
        TAGS(confidential),
        termination_dt
        TAGS(confidential),
        annual_rt
        TAGS(confidential),
        date_of_birth
        TAGS(restricted),
        gender
        TAGS(restricted),
        race
        TAGS(restricted)
    ) AS
    SELECT '0001' AS emplid,
           'John Doe' AS name,
           cast('2024-11-01' AS TIMESTAMP) AS hire_dt,
           cast('2024-11-02' AS TIMESTAMP) AS termination_dt,
  );

...

Row-level Security (RLS)

In addition to column-level security, you can employ row-level security and limit the rows users can see. The VQL below will create a policy and roles for hiding rows based on department.

VQL

Code Block
CREATE OR REPLACE ROLE rls_data_strategy ''
  GRANT CONNECT, METADATA, EXECUTE ON test;
  
CREATE OR REPLACE ROLE rls_iam ''
  GRANT CONNECT, METADATA, EXECUTE ON test;
  
CREATE OR REPLACE ROLE general ''
  GRANT CONNECT, METADATA, EXECUTE ON test;
  
CREATE OR REPLACE TAG rls
    DESCRIPTION = 'Used to tag views and columns with RLS applied';
    
CREATE OR REPLACE TAG rls_dept
    DESCRIPTION = 'Used to tag columns with department values for application of row-level security (RLS)';

CREATE OR REPLACE TAG rls_assigned_roles
    DESCRIPTION = 'Used to tag column containing a users assigned roles';

CREATE OR REPLACE GLOBAL_SECURITY_POLICY rls_dept
    DESCRIPTION = 'Limits rows based on departments associated with users assigned roles'
    ENABLED = TRUE
    AUDIENCE (
        ALL
    )
    ELEMENTS (
        COLUMNS TAGGED ANY (rls_dept)
    )
    RESTRICTION (
        100000.0FILTER AS annual_rt,
           cast('1990-01-01' AS DATE) AS date_of_birth,
           'Male' AS gender,
 = '((strings_have_intersection(''rls_iam,grp_ds_denodo-ir-read'', rls_assigned_roles, '','') AND rls_dept = ''IAM'') OR (strings_have_intersection(''rls_data_strategy,grp_ds_denodo-ir-read'', rls_assigned_roles, '','') AND rls_dept = ''DS''))'
        REJECT 'Unknown'
AS race     FROM dual();

)

...

This can be expanded upon by leveraging user attributes from LDAP/SAML: https://community.denodo.com/kb/en/view/document/How%20to%20implement%20ABAC%20Capabilities%20with%20Global%20Security%20Policies

Demo

Code Block
CREATE OR REPLACE VIEW rlssecurity_test FOLDER = '/02-transformation'
    tagsTAGS (cls, rls_dept) (
    dept tagsTAGS (rls, rls_dept),
    hire_dt TAGS (cls, cls_confidential),
    termination_dt TAGS (cls, cls_confidential),
    annual_rt TAGS (cls, cls_confidential),
    date_of_birth TAGS (cls, cls_restricted, cls_restricted_dob),
    gender TAGS (cls, cls_restricted, cls_restricted_gender),
    race TAGS (cls, cls_restricted, cls_restricted_race),
    raceassigned_roles TAGS (restrictedrls_assigned_roles)
 )
 AS
    with st_union as
    (
      SELECT '0001' AS emplid,
             'John Doe' AS name,
             'DS' AS dept,
             cast('2024-11-01' AS TIMESTAMP) AS hire_dt,
             cast('2024-11-02' AS TIMESTAMP) AS termination_dt,
             100000.0 AS annual_rt,
             cast('1990-01-01' AS DATE) AS date_of_birth,
             'Male' AS gender,
             'Unknown' AS race
      FROM dual()
      UNION ALL
      SELECT '0002' AS emplid,
             'John Doe' AS name,
             'IAM' AS dept,
             cast('2024-11-01' AS TIMESTAMP) AS hire_dt,
             cast('2024-11-02' AS TIMESTAMP) AS termination_dt,
             100000.0 AS annual_rt,
             cast('1990-01-01' AS DATE) AS date_of_birth,
             'Male' AS gender,
             'Unknown' AS race AS DATE) AS date_of_birth,
           FROM dual() 'Male' AS  gender,
)     select * from st_union CONTEXT ('formatted' = 'yes');

...

The queries below demonstrate combinations of CLS and RLS

General

Code Block
select * from test.cls_test context('impersonate_rolesUnknown' AS = 'general');

...

Confidential

Code Block
select * from test.cls_test context('impersonate_roles' = 'confidential');

...

Restricted

Note that the confidential role has been added to restricted so it can satisfy any confidential policy restriction as well

Code Block
select * from test.cls_test context('impersonate_roles' = 'restricted');

...

Department RLS, DS, Confidential

Code Block
select * from test.rls_test context('impersonate_roles'='data_strategy');

...

race
      FROM dual()
    )
    select st_union.*, roles.assigned_roles from st_union left join admin.get_user_roles_string roles on 1=1 CONTEXT ('formatted' = 'yes');

...

The queries below demonstrate combinations of CLS and RLS

General

A user without any CLS or RLS roles

Code Block
select * from test.rlssecurity_test context('impersonate_roles'='iamgeneral');

...

...

Admin

Admin users and roles bypass global security polices so are able to see all rows and columns

Code Block
select 
    * 
from test.rlssecurity_test 
context('impersonate_roles'='data_strategy,iamgrp_ds_denodo-admin');

...

...

Read all, confidential

A role that has “read all” access to rows, coupled with the confidential role

Code Block
select 
    * 
from test.rlssecurity_test 
context('impersonate_roles'='grp_ds_denodo-ir-read,cls_testconfidential');

...

Department

...

role, restricted DOB

A department-specific role, with access to only restricted the DOB column

Code Block
selectselect 
    * 
from test.rlssecurity_test 
context('impersonate_roles'='general');

...

Info

Combining role-based policies for both CLS and RLS together is tricky in Denodo unless the RLS limiting role is also included in an appropriate CLS policy. To prevent role clashing, and simplify implementation, it’s best to implement RLS using session attributes, and CLS using roles.

If a user has a role that isn’t included in the list of included roles of a policy, and that role has execute access to a view, they can bypass that policy for that view. Also, in order for a role in a list of excluded roles in a policy to be effective, it must have the execute privilege on the views in the policy.
rls_data_strategy,cls_restricted_dob');

...

Multiple department roles, restricted and implied confidential access

Code Block
select 
    * 
from test.security_test 
context('impersonate_roles'='rls_data_strategy,rls_iam,cls_restricted');

...

Caching

Denodo applies policies on top of cached data. Since policies do not apply to Administrator user types, users with the serveradmin role, or admins of individual VDB’s, it’s recommended that an admin user be used for caching jobs since this will guarantee that no policies are applied during caching.

...