Titan-Systems / titan

Titan Core - Snowflake infrastructure-as-code. Provision environments, automate deploys, CI/CD. Manage RBAC, users, roles, and data access. Declarative Python Resource API. Change Management tool for the Snowflake data warehouse.
Apache License 2.0
412 stars 24 forks source link

Curious behavior with grant_on_alls: it keeps adding new resources #113

Closed alessio-gastaldo closed 1 month ago

alessio-gastaldo commented 1 month ago

I am using titan-core==0.8.9

As per title, I am observing a weird behavior any time I run my plan and apply for a yaml that include the grant_on_alls block. The behavior is the following:

  1. I create the grants included in the grant_on_alls block using an apply command
  2. I run a plan command on the same yaml file and the same resources (grants in this cases) are scheduled for creation

Here's the file:

roles:
  - name: data_engineer_internal_role
    comment:  "Role dedicated to data engineers in the data team"

role_grants:
  - role: data_engineer_internal_role
    to_role: accountadmin

grants:
  # Grant USAGE on databases
  - to_role: data_engineer_internal_role
    priv: USAGE
    on_database: TEST
  - to_role: data_engineer_internal_role
    priv: USAGE
    on_warehouse: DEV_TESTS

grant_on_alls:
  # Grant USAGE on all schemas in each database
  - to: data_engineer_internal_role
    priv: USAGE
    on_all_schemas_in_database: TEST
  - to: data_engineer_internal_role
    priv: SELECT
    on_all_tables_in_schema: TEST.MY_SCHEMA

  # Grant SELECT on all existing tables in schema
  - to: data_engineer_internal_role
    priv: SELECT
    on_all_tables_in_schema: TEST.ALESSIO_TITAN_DEV

  # Grant SELECT on all existing view in schema
  - to: data_engineer_internal_role
    priv: SELECT
    on_all_views_in_schema: TEST.ALESSIO_TITAN_DEV

future_grants:
  # Grant USAGE  on future schema in the databases
  - to: data_engineer_internal_role
    priv: USAGE
    on_future_schemas_in_database: TEST

  # Grant SELECT on future tables in each schema
  - to: data_engineer_internal_role
    priv: SELECT
    on_future_tables_in_schema: TEST.MY_SCHEMA

And here the plan results:

python -m titan plan --config snowflake/rcdev/roles/data_engineer_internal_role.yml
[titan:SECURITYADMIN] >
        SELECT
            CURRENT_ACCOUNT_NAME() as account,
            CURRENT_ACCOUNT() as account_locator,
            CURRENT_USER() as user,
            CURRENT_ROLE() as role,
            CURRENT_AVAILABLE_ROLES() as available_roles,
            CURRENT_SECONDARY_ROLES() as secondary_roles,
            CURRENT_DATABASE() as database,
            CURRENT_SCHEMAS() as schemas,
            CURRENT_WAREHOUSE() as warehouse,
            CURRENT_VERSION() as version
            (1 rows, 0.21s)
[titan:SECURITYADMIN] > SHOW TAGS IN ACCOUNT    (err 2, 0.19s)
[titan:SECURITYADMIN] > SHOW GRANTS TO ROLE SECURITYADMIN    (10 rows, 0.22s)
[titan:SECURITYADMIN] > SHOW GRANTS TO ROLE PUBLIC    (0 rows, 0.27s)
[titan:SECURITYADMIN] > SHOW GRANTS TO ROLE SYSADMIN    (3 rows, 0.18s)
[titan:SECURITYADMIN] > SHOW GRANTS TO ROLE USERADMIN    (5 rows, 0.20s)
[titan:SECURITYADMIN] > SHOW ROLES IN ACCOUNT    (7 rows, 0.18s)
[titan:SECURITYADMIN] > SHOW FUTURE GRANTS TO ROLE DATA_ENGINEER_INTERNAL_ROLE    (2 rows, 0.18s)
[titan:SECURITYADMIN] > SHOW GRANTS OF ROLE DATA_ENGINEER_INTERNAL_ROLE    (1 rows, 0.73s)
[titan:SECURITYADMIN] > SHOW GRANTS TO ROLE DATA_ENGINEER_INTERNAL_ROLE    (11 rows, 0.24s)
[titan:SECURITYADMIN] > SHOW DATABASES IN ACCOUNT    (3 rows, 0.20s)
[titan:SECURITYADMIN] > SHOW PARAMETERS IN DATABASE TEST    (20 rows, 0.18s)
[titan:SECURITYADMIN] > SHOW SCHEMAS IN ACCOUNT    (24 rows, 0.35s)
[titan:SECURITYADMIN] > SHOW PARAMETERS IN SCHEMA TEST.MY_SCHEMA    (20 rows, 0.20s)
[titan:SECURITYADMIN] > SHOW WAREHOUSES IN ACCOUNT    (2 rows, 0.22s)
[titan:SECURITYADMIN] > SHOW PARAMETERS FOR WAREHOUSE DEV_TESTS    (3 rows, 0.22s)

» titan core
» Plan: 4 to add, 0 to change, 0 to transfer, 0 to destroy.

+ urn::XXXX:grant_on_all/DATA_ENGINEER_INTERNAL_ROLE?priv=USAGE&on=database/TEST.<SCHEMA> {
  + priv         = "USAGE"
  + on_type      = "SCHEMA"
  + in_type      = "DATABASE"
  + in_name      = "TEST"
  + to           = "DATA_ENGINEER_INTERNAL_ROLE"
  + grant_option = False
}

+ urn::XXXX:grant_on_all/DATA_ENGINEER_INTERNAL_ROLE?priv=SELECT&on=schema/TEST.ALESSIO_TITAN_DEV.<TABLE> {
  + priv         = "SELECT"
  + on_type      = "TABLE"
  + in_type      = "SCHEMA"
  + in_name      = "TEST.ALESSIO_TITAN_DEV"
  + to           = "DATA_ENGINEER_INTERNAL_ROLE"
  + grant_option = False
}

+ urn::XXXX:grant_on_all/DATA_ENGINEER_INTERNAL_ROLE?priv=SELECT&on=schema/TEST.ALESSIO_TITAN_DEV.<VIEW> {
  + priv         = "SELECT"
  + on_type      = "VIEW"
  + in_type      = "SCHEMA"
  + in_name      = "TEST.ALESSIO_TITAN_DEV"
  + to           = "DATA_ENGINEER_INTERNAL_ROLE"
  + grant_option = False
}

+ urn::XXXX:grant_on_all/DATA_ENGINEER_INTERNAL_ROLE?priv=SELECT&on=schema/TEST.MY_SCHEMA.<TABLE> {
  + priv         = "SELECT"
  + on_type      = "TABLE"
  + in_type      = "SCHEMA"
  + in_name      = "TEST.MY_SCHEMA"
  + to           = "DATA_ENGINEER_INTERNAL_ROLE"
  + grant_option = False
}

Once the plan is applied the grants are created. However, the next time you try to run a plan, titan brings up these 4 resources again for creation. Is this a wanted behavior? If yes, why?

Thanks, Alessio

titan-teej commented 1 month ago

The GrantOnAll resource is currently designed to always run. I made this decision awhile back, I should be able to clean this up in an upcoming release.

alessio-gastaldo commented 1 month ago

Ok thanks for explaining @titan-teej.