i'm trying to use the EnvoyFilter to pass the jwt payload from the request, decode it and use the claims as headers to the request.
it does not work, and i fail to get the dynamicMetadata filled with the payload after using the jwt_authn.
here is an example of the jwt_authn filter i'm using:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: jwt-filter
namespace: istio-system
spec:
workloadSelector:
labels:
app: app1
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
portNumber: 3000
filterChain:
filter:
name: "envoy.http_connection_manager"
subFilter:
name: "envoy.router"
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.jwt_authn
typed_config:
"#type": "type.googleapis.com/envoy.config.filter.http.jwt_authn.v2alpha.JwtProvider"
providers:
authority_jwks:
issuer: "testing#secure.istio.io"
remote_jwks:
http_uri:
uri: "https://raw.githubusercontent.com/istio/istio/master/security/tools/jwt/samples/jwks.json"
timeout: 5s
cache_duration: 3600s
forward: true
payload_in_metadata: "jwt-metadata"
forward_payload_header: "jwt-header"
i assumed that:
for the first step, if my app is printing the request headers, the jwt-header should be one of the headers and includes the encrypted jwt.
if i'm using an envoy lua filter that gets the DynamicMetadata it will includes the jwt-metadata field.
isnt it?
The JWT filter defaults to extracting the JWT token from "Authorization: Bearer " header. Do you know if Envoy is able to read it?
You can also check envoy logs when running with trace level of logging. It prints jwt_authn logs that show what the filter is doing.
i was able to solve it.
apparently the jwt_authn is used by default when using requetsAuthentication and i dont need to specfically define it on the EnvoyFilter.
what i did, was to add EnvoyFilter of lua script that gets the decryped JWT token like the following:
metadata = request_handle:streamInfo():dynamicMetadata():get("envoy.filters.http.jwt_authn") claims=metadata["testing#secure.istio.io"]
10x
Related
I deployed Neo4j in my AKS cluster using the standalone Helm chart.
It all gets deployed and my Node.js server connects to Neo4j correctly.
However queries throw the Neo4jError: Unknown function 'apoc.convert.fromJsonMap' error, so apoc is clearly missing.
I followed the procedure described here https://neo4j.com/docs/operations-manual/current/kubernetes/configuration/#operations-installing-plugins and my Values are here below.
The only difference I find is that in the guide apoc core is actually enabled afterwards by upgrading the helm chart, while I'm installing it with the option enabled already.
Looking at https://neo4j.com/docs/apoc/current/config/ I saw
As of Neo4j v.5.0, APOC config settings are no longer supported in the neo4j.conf file. Please move all apoc.* settings to apoc.conf. It is also possible to set the config settings using environment variables.
so as neo4j-standalone is using version 4.4.16 I moved the apoc configurations from apoc.config to neo4.config but still apoc procedures are not found by the queries.
Is there something I'm missing out to configure in order to enable apoc?
Thank you very much.
neo4j-db:
# neo4j-standalone:
nameOverride: "neo4j"
fullnameOverride: 'neo4j'
neo4j:
# Name of your cluster
name: "fixit-neo4j" # this will be the label: app: value for the service selector
password: "password"
##
passwordFromSecret: ""
passwordFromSecretLookup: false
edition: "community"
acceptLicenseAgreement: "yes"
offlineMaintenanceModeEnabled: false
resources:
cpu: "1000m"
memory: "2Gi"
volumes:
data:
mode: 'volumeClaimTemplate'
volumeClaimTemplate:
accessModes:
- ReadWriteOnce
storageClassName: neo4j-sc-data
resources:
requests:
storage: 4Gi
backups:
mode: 'share' # share an existing volume (e.g. the data volume)
share:
name: 'logs'
logs:
mode: 'volumeClaimTemplate'
volumeClaimTemplate:
accessModes:
- ReadWriteOnce
storageClassName: neo4j-sc-logs
resources:
requests:
storage: 4Gi
services:
# A ClusterIP service with the same name as the Helm Release name should be used for Neo4j Driver connections originating inside the
# Kubernetes cluster.
default:
# Annotations for the K8s Service object
annotations: { }
# A LoadBalancer Service for external Neo4j driver applications and Neo4j Browser
neo4j:
### this would create cluster-neo4j svc
enabled: false
# env:
# NEO4J_PLUGINS: '["graph-data-science"]'
config:
server.bolt.enabled : "true"
server.bolt.tls_level: "REQUIRED"
server.bolt.listen_address: "0.0.0.0:7687"
dbms.ssl.policy.bolt.client_auth: "NONE"
dbms.ssl.policy.bolt.enabled: "true"
server.directories.plugins: "/var/lib/neo4j/labs"
dbms.security.procedures.unrestricted: "apoc.*"
server.config.strict_validation.enabled: "false"
dbms.security.procedures.allowlist: "gds.*,apoc.*"
apoc_config:
apoc.trigger.enabled: "true"
apoc.jdbc.neo4j.url: "jdbc:foo:bar"
apoc.import.file.enabled: "true"
startupProbe:
failureThreshold: 1000
periodSeconds: 50
ssl:
# setting per "connector" matching neo4j config
bolt:
privateKey:
secretName: tls-secret
subPath: tls.key
publicCertificate:
secretName: tls-secret
subPath: tls.crt
trustedCerts:
sources: [ ]
revokedCerts:
sources: [ ]
OK after a bit of looking at quite a few issues on the same subject, I found that some solutions for this problem was to add dbms.directories.plugins: "/var/lib/neo4j/labs" and dbms.config.strict_validation: "false" in the config section which, as I understand it, mirrors these settings both for server and dbms. It indeed worked, but it's weird that in the official guide it's not mentioned. I mean, these mirrored settings make sense, tell both the server and the dbms where to look for plugins, but still it should be mentioned. I see so many post about this, which means the documentation is not clear enough. It's easy to take things for granted and in fact because this mirrored plugin location both for the server AND dbms need is just not stated anywhere in the docs, I as many others thought that dbms was already configured with the same location as server.directories.plugins: "/var/lib/neo4j/labs" ( which the docs say to configure ) and haven't added it, but hey.. ain't nobody's perfect I guess. Hope they change the docs then for future devs' sake, but meanwhile this answer could be helpful.
So the correct configuration is
env:
NEO4J_PLUGINS: '["graph-data-science"]'
config:
server.bolt.enabled: 'true'
server.bolt.tls_level: 'REQUIRED'
server.bolt.listen_address: '0.0.0.0:7687'
dbms.ssl.policy.bolt.client_auth: 'NONE'
dbms.ssl.policy.bolt.enabled: 'true'
## apoc
server.directories.plugins: '/var/lib/neo4j/labs'
server.config.strict_validation.enabled: 'false'
dbms.security.procedures.unrestricted: 'apoc.*'
dbms.security.procedures.allowlist: 'gds.*,apoc.*'
### additional needed dbms config mirroring server config
dbms.directories.plugins: "/var/lib/neo4j/labs"
dbms.config.strict_validation: "false"
apoc_config:
apoc.trigger.enabled: "true"
apoc.jdbc.neo4j.url: "jdbc:foo:bar"
apoc.import.file.enabled: "true"
It seems the docs are missing installing the APOC plugin. Change the following line to include APOC as well:
NEO4J_PLUGINS: '["graph-data-science", "apoc"]'
and you should be good
I installed the cert-manager using the Helm Chart. I created a ClusterIssuer but I see that it's on a failed state:
kubectl describe clusterissuer letsencrypt-staging
ErrRegisterACMEAccount Failed to register ACME account: invalid character '<' looking for beginning of value
What could be causing this invalid character '<'?
This error is most likely the result of an incorrect server url, the url you specified is returning HTML (hence the complain about <).
Make sure that your server url is https://acme-staging-v02.api.letsencrypt.org/directory" and NOT just https://acme-staging-v02.api.letsencrypt.org/", the directory/ must be included in the url.
So the ClusterIssuer should look like this (emphasis on the .spec.acme.server)
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
email: name.surname#mycompany.com
privateKeySecretRef:
name: letsencrypt-staging
server: https://acme-staging-v02.api.letsencrypt.org/directory
solvers:
- dns01:
route53:
hostedZoneID: XXXXXXXXXXXXXX
region: eu-north-1
selector:
dnsZones:
- xxx.yyy.mycompany.com
Super basic (video) but the title is nearly my comment to Top 3 ways to run your containers on Google Cloud
User Authentication (content) in 2020 about api gateway from endpoints
Maybe a focal point for an answer could be the app engine role for api gateway in 2022. swagger.yaml (#comment)
# openapi2-run.yaml
swagger: "2.0"
info: # >1 API/service; spec x-google-api-name OpenAPI document extension.
title: backbank # mastercard-backbank # API_ID optional-string
#https://cloud.google.com/api-gateway/docs/get-started-cloud-run
description: node cloud run api mastercard p.12 customer keys # Sample API on API Gateway with a Cloud Run backend
version: 0.0.1
security:
- firebase: []
securityDefinitions: #https://cloud.google.com/api-gateway/docs/authenticating-users-firebase
firebase: #bearer https://cloud.google.com/endpoints/docs/openapi/openapi-extensions
authorizationUrl: "" # empty for firebase frm bearer Authorization?
flow: "implicit"
type: "oauth2"
x-google-issuer: "https://securetoken.google.com/vaumoney"
x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken#system.gserviceaccount.com"
x-google-audiences: "vaumoney"
host: "vault-co.in"
basePath: "/" # https://stackoverflow.com/questions/71258737/making-a-cloud-firestore-rest-api-call-through-cloud-endpoints
#When the basePath property is configured in the service configuration as well,
#this header applies only to URL paths that are prefixed by the basePath property value.
#URLs that aren't part of the basePath aren't passed through regardless of the x-google-allow property.
schemes:
- https
consumes:
- application/json
produces:
- application/json
#x-google-allow:
#all
#jwt_audience: https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken#system.gserviceaccount.com/vaumoney
#x-google-endpoints:
#- name: "vault-co.in"
#allowCors: True
paths:
/:
get:
summary: Yes Hello cloud run (api gateway, load balance) service
operationId: get
x-google-backend:
address: https://vault-co.in:8080 # APP_URL endpoint(s)
protocol: h2
responses:
200:
description: This is a (Non-Graphical) Application Programming Interface
#schema:
#type: string
#default: '''ello guv'''
default:
description: Something is wrong
#schema:
#type: string
#default: '''some not 200'''
options:
summary: Enable CORS with headers
operationId: options
x-google-backend:
address: https://vault-co.in:8080 # APP_URL endpoint(s)
jwt_audience: https://vault-co.in
protocol: h2
description: |
Origin, Methods and Headers allowing headers potentially requested
tags:
- CORS
responses:
200:
description: OPTIONS responding headers
headers:
Access-Control-Allow-Origin:
type: string
#$ref: '#/definitions/String'
default: "'i7l8qe.csb.app'"
Access-Control-Allow-Methods:
type: string
default: "'GET,POST'"
Access-Control-Allow-Headers:
type: string
default: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
403:
description: OPTIONS responding headers
headers:
Access-Control-Allow-Origin:
type: string
default: "'i7l8qe.csb.app'" # '''vau.money'''
Access-Control-Allow-Methods:
type: string
default: "'GET,POST'"
Access-Control-Allow-Headers:
type: string
default: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
#content: {}
default:
description: Something is wrong
#type: string
#default: '''some not 200'''
post:
summary: Respond properly indeed
operationId: posted
x-google-backend:
address: https://vault-co.in:8080 # APP_URL endpoint(s)
jwt_audience: https://vault-co.in
protocol: h2
description: |
Successful api fetch
parameters:
- name: pageOffset
in: body
required: true
schema:
type: object
properties:
pageOffset:
description: pageOffset is required, try 0
type: string
pageLength:
description: pageLength is required, try 10
type: string
postalCode:
description: postalCode is required, try 11101
type: string
responses: # https://swagger.io/docs/specification/describing-responses/
default: #200
description: post result
#content:v3 application/json:
schema:
type: object
description: response ok
required:
- results
properties:
results:
#collectionFormat: csv
type: array
default: []
items:
type: string
meta:
type: object
properties:
title:
type: string
description:
type: string
I repeat attempts in seriatim:
gcloud api-gateway gateways delete backbank --location=us-central1
gcloud api-gateway api-configs delete backbank --api=backbank
gcloud api-gateway api-configs create backbank --api=backbank --openapi-spec=swagger.yaml --project=vaumoney --backend-auth-service-account=vaumoney#appspot.gserviceaccount.com
(a) gcloud endpoints services deploy swagger.yaml --project=vaumoney
(b) gcloud services enable vault-co.in (Principal-role permission name: "firebase-adminsdk")
gcloud run deploy backbank \
--image="gcr.io/vaumoney/endpoints-runtime-serverless:2.38.0-vault-co.in-2022-09-08r2" \
--set-env-vars ESPv2_ARGS=^++^--cors_preset=cors_with_regex++--cors_allow_origin_regex=^https:[/][/]i7l8qe.csb.app$++--cors_allow_methods=GET,POST,OPTIONS++--cors_allow_headers=Origin,Content-Type,Authorization,Referrer-Policy++--cors_allow_credentials \
--platform managed --project vaumoney
Of course, I incessantly get this:
The request was not authenticated. Either allow unauthenticated invocations or set the proper Authorization header. Read more at https://cloud.google.com/run/docs/securing/authenticating Additional troubleshooting documentation can be found at: https://cloud.google.com/run/docs/troubleshooting#unauthorized-client
But OPTIONS might be the problem (albeit "" on GET):
"This would be really useful for us, we're using cloud run for all our microservices and want to call these from a SPA via API Gateway." "We're back to Cloud Endpoints and ESPv2 for the time being, but we 100% see the benefits of the managed API Gateway, should CORS support be available for gRPC requests."
What am I to do?
I have the following imagepolicy:
apiVersion: image.toolkit.fluxcd.io/v1alpha2
kind: ImagePolicy
metadata:
name: cps-kul-beta-imagepolicy
namespace: flux-system
spec:
imageRepositoryRef:
name: cps-kul-image
filterTags:
pattern: '^sha-(?P<ts>.*)-.+'
extract: '$ts'
policy:
numerical:
order: asc
And I get the error version list argument cannot be empty when doing kubectl describe on that object.
This error means that there's no images in the registry which conform to the tag pattern prescribed in the filterTags section. Uploading a new image to the registry will fix this problem.
Is there a way to pass a boolean value for spec.container.env.value ?
I want to override, with helm, a boolean env variables in a docker parent image (https://github.com/APSL/docker-thumbor) : UPLOAD_ENABLED
I made a simpler test
If you try the following yaml :
apiVersion: v1
kind: Pod
metadata:
name: envar-demo
labels:
purpose: demonstrate-envars
spec:
containers:
- name: envar-demo-container
image: gcr.io/google-samples/node-hello:1.0
env:
- name: DEMO_GREETING
value: true
And try to create it with kubernetes, you got the following error :
kubectl create -f envars.yaml
the error :
error: error validating "envars.yaml": error validating data: expected type string, for field spec.containers[0].env[0].value, got bool; if you choose to ignore these errors, turn validation off with --validate=false
with validate=false
Error from server (BadRequest): error when creating "envars.yaml": Pod in version "v1" cannot be handled as a Pod: [pos 192]: json: expect char '"' but got char 't'
It doesn't work with integer values too
spec.container.env.value is defined as string. see here:
https://kubernetes.io/docs/api-reference/v1.6/#envvar-v1-core
You'd have to cast/convert/coerse to boolean in your container when using this value
Try escaping the value. The below worked for me:
- name: DEMO_GREETING
value: "'true'"
This works for me.
In my example, one is hardcoded, and the other comes from an env var.
env:
- name: MY_BOOLEAN
value: 'true'
- name: MY_BOOLEAN2
value: '${MY_BOOLEAN2_ENV_VAR}'
So basically, I wrap single quotes around everything, just in case.
WARNING: Dont use hyphens in your env var names, that will not work...
if you are the helm chart implementer, just quote it
data:
# VNC_ONLY: {{ .Values.vncOnly }} <-- Wrong
VNC_ONLY: "{{ .Values.vncOnly }}" # <-- Correct
From command line you can also use
--set-string
instead of
--set
and you will be able to pass value without escaping
for instance:
--set-string "env.my-setting=False"