Installation
To install the Platfom BigQuery interceptor:
- First, pull the BigQuery interceptor container image from PlainID Container Registry using the docker pull command:
docker pull <platform registry location>:<version>
For example:
docker pull gcr.io/plainid-presales/bigquery:1.0
- Create a secret from the credentials JSON:
Note - The credentials JSON
kubectl create secret generic google-creds --from-file=<json location>
For example:
kubectl create secret generic google-creds --from-file=query-enforcer/creds.json
- Make the required changes in bigq.yaml. Check the Sample Configuration below
- Apply the
bigq.yaml
kubectl apply -f bigq.yaml
Sample Configuration bigq.yaml
This sample bigq.yaml
contains the following yamls:
- Configmap
- Service
- Deployment
- Secret (Optional)
apiVersion: v1
data:
application.properties: |
server.port=8080
#server.tomcat.uri-encoding=UTF-8
#server.error.whitelabel.enabled=false
logging.config=classpath:logback-spring.xml
# The PlainID logging level options include trace, debug, info, error, and OFF.
logging.level.org.springframework=OFF
logging.level.org.springframework.core=OFF
logging.level.org.springframework.beans=OFF
logging.level.org.springframework.context=OFF
logging.level.org.springframework.transaction=OFF
logging.level.org.springframework.web=OFF
logging.level.org.springframework.test=OFF
logging.level.org.springframework.data=OFF
logging.level.com.google.zetasql=info
logging.level.com.plainid=error
spring.main.banner-mode=OFF
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
spring.redis.host=redis.example.com
spring.redis.port=6379
spring.redis.password=SXSIvHJo1OzaWnU2YHZ8p3us0z
spring.data.redis.ssl.enabled=true
management.security.enabled=false
management.endpoints.enabled-by-default=false
management.endpoints.web.exposure.include=info, health
management.endpoint.info.enabled=true
management.endpoint.health.enabled=true
management.endpoint.health.show-components=always
management.endpoint.health.show-details=always
management.endpoint.health.probes.enabled=true
management.endpoint.health.group.liveness.include=livenessState
management.endpoint.health.group.liveness.show-details=always
management.endpoint.health.group.readiness.include=readinessState
management.endpoint.health.group.readiness.show-details=always
management.health.postgres.enabled=true
management.health.readinessstate.enabled=true
management.info.git.mode=full
spring.cloud.gcp.core.enabled=false
spring.cloud.gcp.bigquery.enabled=false
app.request-context.prefix=context
# update the following parameter to your PDP URL
app.policy-resolution.api-url=https://URL-TO-PDP-RUNTIME/api/runtime/resolution/v3
app.cache.prefix=query-enforcer.v2
app.cache.ttl-policy-resolution=3000
app.cache.ttl-db-schema-initial-delay=3000
app.cache.ttl-db-schema=600000
app.cache.ttl-catalog=300000
# update to the full path of the GCP Service Account Credentials file:
app.enforcer.bigquery-credential-files[0]=file:creds.json
app.enforcer.resolutionresponse-empty=deny
app.enforcer.resolutionaccess-empty=deny
app.enforcer.resolutionprivileges-empty=allow
app.enforcer.ignoreforbidden-columns=deny
app.enforcer.columnenforcermasks[string]=***
app.enforcer.resolutionmasking-as-column=deny
app.enforcer.resolution-attribute-projectId=projectid
app.enforcer.resolution-attribute-dataset=dataset
app.enforcer.resolution-attribute-table=table
app.enforcer.resolution-attribute-column=column
app.enforcer.bigquery-information-schema=allow
app.enforcer.ignore-enforcer-fails=deny
# app.enforcer.ignore-tables[0]=plainid-142815.*.*
app.enforcer.ignore-forbidden-columns=deny
# SSL configuration (Uncomment to enable SSL)
# The format used for the keystore. It could be set to JKS in case it is a JKS file
# server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
# server.ssl.key-store=/app/keystore.jks
# The password used to generate the certificate
# server.ssl.key-store-password=111
# The alias mapped to the certificate
# server.ssl.key-alias=111
# security.require-ssl=false
kind: ConfigMap
metadata:
name: bigq-config
---
apiVersion: v1
kind: Service
metadata:
name: bigq
spec:
selector:
app: bigq
ports:
- name: "bigq"
protocol: "TCP"
port: 8080
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: bigq
spec:
selector:
matchLabels:
app: bigq
strategy:
rollingUpdate:
maxSurge: 2
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
app: bigq
spec:
containers:
# The following 3 lines are optional - depending on the used redis - internal or managed
- image: redis
name: redis
resources: {}
# Use the Image and Tag provided by PlainID
- image: plainid/authz-bigquery:5.2321.0
imagePullPolicy: Always
name: bigq
resources: {}
volumeMounts:
- name: bigq
mountPath: /app/application.properties
subPath: application.properties
- name: creds
mountPath: /app/creds.json
# The name of the credentials JSON file - matching the name of the local file `creds.json`
subPath: creds.json
volumes:
- name: bigq
configMap:
name: bigq-config
- name: creds
secret:
secretName: google-creds
Configuration Properties
Property | Description | Values |
---|---|---|
app.policy-resolution.api-url |
The runtime resolution API URL | Example: https://localhost:8010/api/runtime/resolution/v3 |
app.policy-resolution.connection-timeout |
Sets the connection timeout in milliseconds | Default: 10000 |
app.policy-resolution.socket-timeout |
Sets the socket timeout in milliseconds | Default: 60000 |
app.policy-resolution.automatic-retries |
Toggle disabling automatic retries (up to 4 times) for socket timeouts | Default: true |
app.bigquery.total-timeout |
totalTimeout has ultimate control over how long the logic should keep trying the remote call until it gives up completely. The higher the total timeout, the more retries can be attempted. | Default: 0 milliseconds |
app.bigquery.initial-retry-delay |
InitialRetryDelay controls the delay before the first retry. Subsequent retries will use this value adjusted according to the RetryDelayMultiplier. | Default: 0 milliseconds |
app.bigquery.max-retry-delay |
MaxRetryDelay puts a limit on the value of the retry delay, so that the RetryDelayMultiplier can't increase the retry delay higher than this amount. | Default: 0 milliseconds |
app.bigquery.retry-delay-multiplier |
RetryDelayMultiplier controls the change in retry delay. The retry delay of the previous call is multiplied by the RetryDelayMultiplier to calculate the retry delay for the next call. | Default: 1.0 |
app.bigquery.max-attempts |
MaxAttempts defines the maximum number of attempts to perform. If this value is greater than 0, and the number of attempts reaches this limit, the logic will give up retrying even if the total retry time is still lower than TotalTimeout. | Default: 0 |
app.cache.prefix |
Redis cache prefix | Default: query-enforcer.v2 |
app.cache.ttl-policy-resolution |
Cache TTL in milliseconds for Policy Resolution response | Default: 300000 (5m) Minimum: 2000 (2s) |
app.cache.ttl-db-schema |
Cache TTL in milliseconds for BigQuery request | Default: 10800000 (3h) Minimum: 60000 (1m) |
app.cache.ttl-catalog |
Cache TTL in milliseconds for building internal DB schema for dataset from enforcer request | Default: 600000 (10m) Minimum: 10000 (10s) |
app.enforcer.bigquery-credential-files |
List of GCP credential filenames if empty or not defined the workload identity will be used for authentication. The first credentials file is used as default in cases where the project user is querying doesn't have a designated file. |
Example: app.enforcer.bigquery-credential-files[0]=project-12345.json |
app.enforcer.resolution-response-empty |
How to act in case there is no response (empty response) from the Policy Decision Point. allow – enable access without any limitations. deny – block all access. |
Default: deny |
app.enforcer.resolution-access-empty |
How to act in case response includes row level policy only (no column level response). allow – All columns are returned to the user. deny – All columns are masked. |
Default: deny |
app.enforcer.resolution-privileges-empty |
How to act in case the response includes column level policy only, (No row level response). allow – no limitation on row level. deny – no rows are returned to the user |
Default: deny |
app.enforcer.resolution-masking-as-column |
How to act in case the response from Policy Decision Point does not contain any access but does contain masking instruction.allow – mask all columns in the table based on masking instructions.deny – block all access. Note: this is relvant only when app.enforcer.resolution-response-empty is defined as |
Default: deny |
app.enforcer.resolution-attribute-projectId |
Name of "projectId" attribute in policy Asset Template | Default: projectid |
app.enforcer.resolution-attribute-dataset |
Name of "dataset" attribute in policy Asset Template | Default: dataset |
app.enforcer.resolution-attribute-table |
Name of "table" attribute in policy Asset Template | Default: table |
app.enforcer.resolution-attribute-column |
Name of "column" attribute in policy Asset Template | Default: column |
app.enforcer.resolution-masking-resource-type-name |
Name of the Asset Template used to manage masking instructions V2.4 and above |
Default: Masking_Instructions |
app.enforcer.resolution-attribute-maskAs |
Name of attribute used to manage the masking instruction within the Asset Template V2.4 and above |
Default: maskas |
app.enforcer.bigquery-information-schema |
Supporting queries with using information_schema tables. Possible values: allow or deny . After changing this value the DB schema cache must be updated. |
Default: allow |
app.enforcer.ignore-enforcer-fails |
Indicates what to do in case a SQL query that can’t be parsed is sent to the enforcer. Possible values: allow or deny |
Default: deny |
app.enforcer.ignore-tables |
List of tables with full name “project.dataset.table” to ignore for enforcing. It is possible to use “*” (star) instead of name for each part. | Example: app.enforcer.ignore-tables[0]=*.*.members |
app.enforcer.ignore-forbidden-columns |
A behavior of using a forbidden column is sent within the WHERE clause of SQL query. Possible values: allow or deny |
Default: deny |
app.enforcer.bigquery-prefetch-db-schema |
Filtering used metadata based on mentioned tables in SQL. If If V2.2 and above |
Default: true |
app.enforcer.column-enforcer-masks[coulmnType] |
Define default masking instruction per Column Type. Will be considered in case no masking instruction will return from the Policy Decision Point V2.4 and above | Examples:app.enforcer.column-enforcer-masks[string]=*** app.enforcer.column-enforcer-masks[numerical]=-1 app.enforcer.column-enforcer-masks[bool]=false app.enforcer.column-enforcer-masks[timestamp]=0 app.enforcer.column-enforcer-masks[date]=2007-12-03 app.enforcer.column-enforcer-masks[time]=10:15:30 |
Optional Configuration to create the secret on-the-fly
Append the following yaml to the bigq.yaml
:
apiVersion: v1
metadata:
name: google-creds
data:
creds.json: the-gcp-iam-service-user-credentials-content
kind: Secret
Configuration
Required Parameters/Attributes
Parameter/Attribute | Description | Example |
---|---|---|
data:creds.json |
the IAM certificate content (obtained from Google Cloud Platform IAM) |
{
"type": "service_account",
"project_id": "example",
"private_key_id": "867b49f1cb844f1757d6265e3608f814a05b4bce",
"private_key": "-----BEGIN PRIVATE KEY-----\nMII...\n-----END PRIVATE KEY-----\n",
"client_email": "bigquery@example.iam.gserviceaccount.com",
"client_id": "930123456789012345678",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/bigquery%40example.iam.gserviceaccount.com"
}
|
app.policy-resolution.api-url |
The URL to the PlainID PDP Policy Resolution API End-Point | Cloud: https://[your-tenant].[data-center].plainid.io/api/runtime/resolution/v3 Policy Authorization Agent: Customer Hosted Platform: |