Skip to content

Commit 970da87

Browse files
committed
WIP for Maxi :)
1 parent e5ff314 commit 970da87

36 files changed

Lines changed: 1297 additions & 365 deletions

_TEST/CURLS.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
curl 'localhost:9477/metadata/database?system=trino&instance=kuttl-secure-hermit-wf84/my-trino&database=tpch' | jq
2+
curl 'localhost:9477/metadata/schema?system=trino&instance=kuttl-secure-hermit-wf84/my-trino&database=tpch&schema=sf1' | jq
3+
curl 'localhost:9477/metadata/table?system=trino&instance=kuttl-secure-hermit-wf84/my-trino&database=tpch&schema=sf1&table=customer' | jq
4+
curl 'localhost:9477/metadata/stream?system=kafka&instance=kuttl-secure-hermit-wf84/test-kafka&queue=orders' | jq
5+
curl 'localhost:9477/metadata/dashboard?system=superset&instance=kuttl-secure-hermit-wf84/my-superset&id=1' | jq
6+
curl 'localhost:9477/metadata/chart?system=superset&instance=kuttl-secure-hermit-wf84/my-superset&id=1' | jq
7+
8+
curl 'localhost:9477/metadata/rawIdentifier?identifier=urn:li:container:792ce6aace288712a1ef036fbca2bb37' | jq
9+
curl 'localhost:9477/metadata/rawIdentifier?identifier=urn:li:container:ae5d10cb199e26e8df70c7563e6d1c58' | jq
10+
curl 'localhost:9477/metadata/rawIdentifier?identifier=urn:li:dataset:(urn:li:dataPlatform:trino,kuttl-secure-hermit-wf84/my-trino.tpch.sf1.customer,PROD)' | jq
11+
curl 'localhost:9477/metadata/rawIdentifier?identifier=urn:li:dataset:(urn:li:dataPlatform:kafka,kuttl-secure-hermit-wf84/test-kafka.orders,PROD)' | jq
12+
curl 'localhost:9477/metadata/rawIdentifier?identifier=urn:li:dashboard:(superset,kuttl-secure-hermit-wf84/my-superset.1)' | jq
13+
curl 'localhost:9477/metadata/rawIdentifier?identifier=urn:li:chart:(superset,kuttl-secure-hermit-wf84/my-superset.1)' | jq

docs/modules/opa/pages/usage-guide/resource-info-fetcher.adoc

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
:description: Resource Info Fetcher for OPA retrieves data from backends like DataHub. Integrate extra resource details into Rego rules for enhanced policy management.
33

44
The _Resource info fetcher_ allows for additional information to be obtained from the configured backend (for example, DataHub).
5-
You can then write Rego rules for OpenPolicyAgent which make an HTTP request to the Resource info fetcher and make use of the additional information returned for the resource, such as Trino tables or Kafka topic.
5+
You can then write Rego rules for OpenPolicyAgent which make an HTTP request to the Resource info fetcher and make use of the additional information returned for the resource, such as Trino tables or Apache Kafka topics.
66

77
You can enable the Resource info fetcher sidecar as follows:
88

@@ -45,7 +45,7 @@ stringData:
4545
<1> Enable the `resource-info-fetcher` sidecar
4646
<2> Enable TLS verification using the CA from the `tls` SecretClass.
4747
<3> Authenticate to DataHub with a Personal Access Token (PAT) read from the specified Secret. The Secret must have a `token` entry. See the DataHub documentation on https://docs.datahub.com/docs/authentication/personal-access-tokens[Personal Access Tokens] for how to create one, and make sure https://docs.datahub.com/docs/authentication/introducing-metadata-service-authentication[Metadata Service Authentication] is enabled on your DataHub.
48-
<4> The DataHub environment (fabric) to query, e.g. `PROD` or `DEV`. Defaults to `PROD`.
48+
<4> The DataHub environment (fabric) to query, e.g. `PROD` or `DEV`. Defaults to `PROD`, which is also what DataHub's ingestion sources default to.
4949

5050
Currently the following backends are supported:
5151

@@ -65,7 +65,33 @@ DataHub is currently only supported backend, so the general documentation from a
6565

6666
== Resource info fetcher API
6767

68-
Resource information can be retrieved from regorules using the functions `TODO` in `data.stackable.opa.resourceinfo.v1`.
68+
Resource information can be retrieved from regorules using the functions in `data.stackable.opa.resourceinfo.v1`.
69+
There is one function per kind of resource:
70+
71+
[source,rego]
72+
----
73+
databaseResourceInfo(system, instance, database)
74+
schemaResourceInfo(system, instance, database, schema)
75+
tableResourceInfo(system, instance, database, schema, table)
76+
streamResourceInfo(system, instance, queue)
77+
dashboardResourceInfo(system, instance, id)
78+
chartResourceInfo(system, instance, id)
79+
80+
rawIdentifierResourceInfo(identifier)
81+
----
82+
83+
The naming is intentionally product-agnostic, so that one function serves the equivalent resource of every product.
84+
`databaseResourceInfo` addresses what Trino calls a catalog, and `streamResourceInfo` what Apache Kafka calls a topic.
85+
86+
`rawIdentifierResourceInfo` is the escape hatch for resources the functions above do not cover: it passes the identifier to the backend as-is.
87+
For DataHub that is a URN, such as `urn:li:chart:(superset,my-namespace/my-superset.1)`.
88+
89+
The first two arguments are the same everywhere:
90+
91+
* `system` is the kind of product the resource lives in, for example `trino`, `kafka` or `superset`. DataHub calls this the _data platform_.
92+
* `instance` identifies _which_ deployment of that product, for example `my-namespace/my-trino`. DataHub calls this the _platform instance_, and the value must match the `platform_instance` of the ingestion source that produced the metadata.
93+
94+
The DataHub environment (fabric) is deliberately *not* an argument: it describes how the catalog was populated rather than the resource being authorized, so it is configured once on the OpaCluster (see `env` above) instead of being passed in by every Rego rule.
6995

7096
An example of the returned structure:
7197

@@ -99,22 +125,41 @@ An example of the returned structure:
99125

100126
=== Debug request
101127

102-
To debug the resource-info-fetcher you can `curl` it's API for a given resource.
128+
To debug the resource-info-fetcher you can `curl` its API for a given resource.
129+
Every Rego function above maps to a `GET /metadata/<resource type>` endpoint that takes its arguments as query parameters.
103130
To achieve this shell into the `opa` container and execute
104131

105132
[source,bash]
106133
----
107-
curl --header 'Content-Type: application/json' -d '{"stacklet": "trino", "trinoSchema": {"catalog": "lakehouse", "schema": "customer_analytics"}}' localhost:9477/resource | jq
134+
curl 'localhost:9477/metadata/schema?system=trino&instance=my-namespace/my-trino&database=lakehouse&schema=customer_analytics' | jq
135+
136+
curl 'localhost:9477/metadata/chart?system=superset&instance=my-namespace/my-superset&id=1' | jq
108137
109-
curl --header 'Content-Type: application/json' -d '{"stacklet": "", "dataHubUrn": "urn:li:chart:(superset,1)"}' localhost:9477/resource | jq
138+
curl 'localhost:9477/metadata/rawIdentifier?identifier=urn:li:chart:(superset,my-namespace/my-superset.1)' | jq
110139
----
111140

112141
=== Rego rule library
113142

114143
The HTTP API exposed by the resource-info-fetcher can be called directly using the rego function `http.send`.
115144
However, we provide a convenience rego rule library, which we ship with `OpaClusters` by default.
116145

146+
For example, the following rule allows access to tables tagged as `public`:
147+
117148
[source,rego]
118149
----
119-
TODO
150+
package test
151+
152+
import data.stackable.opa.resourceinfo.v1 as resourceinfo
153+
154+
default allow := false
155+
156+
allow if {
157+
table := resourceinfo.tableResourceInfo("trino", "my-namespace/my-trino", input.catalog, input.schema, input.table)
158+
some tag in table.tags
159+
tag.urn == "urn:li:tag:public"
160+
}
120161
----
162+
163+
A resource the backend does not know about is not reported as an error: the resource-info-fetcher returns a record with empty `tags`, `owners` and `dataProducts` and a `null` `domain`.
164+
Prefer rules that require a positive signal, like the one above, which denies access in that case.
165+
A rule that merely excludes a tag would instead grant access to every resource missing from the backend.

extra/crds.yaml

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ spec:
5959
catalog.
6060
6161
Data catalog could e.g. be DataHub and resources could be Trino catalogs, schemas,
62-
tables or Kafka topic etc.
62+
tables or Kafka topics etc.
6363
nullable: true
6464
properties:
6565
backend:
@@ -83,7 +83,41 @@ spec:
8383
type: string
8484
env:
8585
default: PROD
86-
description: The env in DataHub, defaults to `PROD`
86+
description: |-
87+
The DataHub environment (in DataHub terms: the fabric) the resources live in.
88+
89+
This must match the `env` of the DataHub ingestion source that produced the metadata,
90+
because `env` is part of the dataset URN (and of the container key that database and
91+
schema URNs are hashed from). A mismatch is not reported as an error: the constructed URN
92+
simply does not resolve and the resource-info-fetcher returns empty metadata.
93+
94+
This is configured here rather than passed in by the Rego rule on purpose. `env`
95+
describes how the catalog was populated, not the resource that is being authorized, and
96+
the Rego rule has no way of knowing it. It is also DataHub-specific: no other metadata
97+
catalog we know of has this concept.
98+
99+
`env` is largely superseded by DataHub's platform instance, which the Rego rules already
100+
pass as `instance` — within a single DataHub, a platform instance belongs to exactly one
101+
fabric. Should a single resource-info-fetcher ever need to serve multiple fabrics, we
102+
would add per-instance `envOverrides` here instead of moving `env` back into the API.
103+
enum:
104+
- DEV
105+
- TEST
106+
- QA
107+
- UAT
108+
- EI
109+
- PRE
110+
- STG
111+
- NON_PROD
112+
- PROD
113+
- CORP
114+
- RVW
115+
- PRD
116+
- TST
117+
- SIT
118+
- SBX
119+
- SANDBOX
120+
- CERT
87121
type: string
88122
hostname:
89123
description: Hostname of DataHub
@@ -2256,7 +2290,7 @@ spec:
22562290
catalog.
22572291
22582292
Data catalog could e.g. be DataHub and resources could be Trino catalogs, schemas,
2259-
tables or Kafka topic etc.
2293+
tables or Kafka topics etc.
22602294
nullable: true
22612295
properties:
22622296
backend:
@@ -2280,7 +2314,41 @@ spec:
22802314
type: string
22812315
env:
22822316
default: PROD
2283-
description: The env in DataHub, defaults to `PROD`
2317+
description: |-
2318+
The DataHub environment (in DataHub terms: the fabric) the resources live in.
2319+
2320+
This must match the `env` of the DataHub ingestion source that produced the metadata,
2321+
because `env` is part of the dataset URN (and of the container key that database and
2322+
schema URNs are hashed from). A mismatch is not reported as an error: the constructed URN
2323+
simply does not resolve and the resource-info-fetcher returns empty metadata.
2324+
2325+
This is configured here rather than passed in by the Rego rule on purpose. `env`
2326+
describes how the catalog was populated, not the resource that is being authorized, and
2327+
the Rego rule has no way of knowing it. It is also DataHub-specific: no other metadata
2328+
catalog we know of has this concept.
2329+
2330+
`env` is largely superseded by DataHub's platform instance, which the Rego rules already
2331+
pass as `instance` — within a single DataHub, a platform instance belongs to exactly one
2332+
fabric. Should a single resource-info-fetcher ever need to serve multiple fabrics, we
2333+
would add per-instance `envOverrides` here instead of moving `env` back into the API.
2334+
enum:
2335+
- DEV
2336+
- TEST
2337+
- QA
2338+
- UAT
2339+
- EI
2340+
- PRE
2341+
- STG
2342+
- NON_PROD
2343+
- PROD
2344+
- CORP
2345+
- RVW
2346+
- PRD
2347+
- TST
2348+
- SIT
2349+
- SBX
2350+
- SANDBOX
2351+
- CERT
22842352
type: string
22852353
hostname:
22862354
description: Hostname of DataHub

rust/operator-binary/src/controller/build/resource/daemonset/resource_info_fetcher.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ use crate::{
1717
self,
1818
resource::daemonset::{
1919
CONFIG_DIR, CONFIG_VOLUME_NAME, RESOURCE_INFO_FETCHER_CREDENTIALS_DIR,
20-
RESOURCE_INFO_FETCHER_CREDENTIALS_VOLUME_NAME,
21-
add_stackable_rust_cli_env_vars, container_name, sidecar_container_log_level,
22-
sidecar_resource_requirements,
20+
RESOURCE_INFO_FETCHER_CREDENTIALS_VOLUME_NAME, add_stackable_rust_cli_env_vars,
21+
container_name, sidecar_container_log_level, sidecar_resource_requirements,
2322
},
2423
},
2524
},

rust/operator-binary/src/crd/resource_info_fetcher/mod.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,91 @@ pub mod versioned {
4646
///
4747
/// Must contain the field `token`.
4848
pub credentials_secret_name: SecretName,
49+
50+
/// The DataHub environment (in DataHub terms: the fabric) the resources live in.
51+
///
52+
/// This must match the `env` of the DataHub ingestion source that produced the metadata,
53+
/// because `env` is part of the dataset URN (and of the container key that database and
54+
/// schema URNs are hashed from). A mismatch is not reported as an error: the constructed URN
55+
/// simply does not resolve and the resource-info-fetcher returns empty metadata.
56+
///
57+
/// This is configured here rather than passed in by the Rego rule on purpose. `env`
58+
/// describes how the catalog was populated, not the resource that is being authorized, and
59+
/// the Rego rule has no way of knowing it. It is also DataHub-specific: no other metadata
60+
/// catalog we know of has this concept.
61+
///
62+
/// `env` is largely superseded by DataHub's platform instance, which the Rego rules already
63+
/// pass as `instance` — within a single DataHub, a platform instance belongs to exactly one
64+
/// fabric. Should a single resource-info-fetcher ever need to serve multiple fabrics, we
65+
/// would add per-instance `envOverrides` here instead of moving `env` back into the API.
66+
#[serde(default)]
67+
pub env: FabricType,
68+
}
69+
70+
/// DataHub's `FabricType`: the environments (in DataHub terms: fabrics) a resource can live in.
71+
///
72+
/// The variants serialize exactly the way DataHub spells them, so a value can be copied from an
73+
/// ingestion recipe or the DataHub UI as-is.
74+
///
75+
/// See the [`FabricType` definition] in DataHub's metadata model.
76+
///
77+
/// [`FabricType` definition]: https://github.com/datahub-project/datahub/blob/master/li-utils/src/main/pegasus/com/linkedin/common/FabricType.pdl
78+
#[derive(
79+
Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize, strum::Display,
80+
)]
81+
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
82+
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
83+
pub enum FabricType {
84+
/// Development fabrics.
85+
Dev,
86+
87+
/// Testing fabrics.
88+
Test,
89+
90+
/// Quality assurance fabrics.
91+
Qa,
92+
93+
/// User acceptance testing fabrics.
94+
Uat,
95+
96+
/// Early-integration fabrics.
97+
Ei,
98+
99+
/// Pre-production fabrics.
100+
Pre,
101+
102+
/// Staging fabrics.
103+
Stg,
104+
105+
/// Non-production fabrics.
106+
NonProd,
107+
108+
/// Production fabrics. DataHub's ingestion sources default to this fabric, so we do as well.
109+
#[default]
110+
Prod,
111+
112+
/// Corporation fabrics.
113+
Corp,
114+
115+
/// Review fabrics.
116+
Rvw,
117+
118+
/// Alternative spelling of [`Self::Prod`], which DataHub accepts as well.
119+
Prd,
120+
121+
/// Alternative spelling of [`Self::Test`], which DataHub accepts as well.
122+
Tst,
123+
124+
/// System integration testing fabrics.
125+
Sit,
126+
127+
/// Alternative spelling of [`Self::Sandbox`], which DataHub accepts as well.
128+
Sbx,
129+
130+
/// Sandbox fabrics.
131+
Sandbox,
132+
133+
/// Certification fabrics.
134+
Cert,
49135
}
50136
}

0 commit comments

Comments
 (0)