How do I define a multiline key in docker-compose.yml?
I tried diff solutions:
environment:
- PRIVATE_KEY= |-
-----BEGIN RSA PRIVATE KEY-----
line2
environment:
- PRIVATE_KEY= |
-----BEGIN RSA PRIVATE KEY-----
line2
environment:
- PRIVATE_KEY= !
-----BEGIN RSA PRIVATE KEY-----
line2
environment:
- PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nline2"
environment:
- PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n\nline2"
Resources:
https://yaml-multiline.info/
https://gist.github.com/usmansaleem/bb47064f406c105fdfa69716544b7b8e
But none of them formatted the private key in a proper way.
Edit (Addition):
environment:
- PRIVATE_KEY: |-
-----BEGIN RSA PRIVATE KEY-----
line2
The only key in your "test" document is the scalar environment, the other scalars are all unquoted multi-line scalar values.
You refer to a document that explains how to do literal scalars, but you never try those, as this
- PRIVATE_KEY= |-
-----BEGIN RSA PRIVATE KEY-----
line2
is the same as doing
- PRIVATE_KEY= |- -----BEGIN RSA PRIVATE KEY----- line2
i.e. the |- doesn't have any special function except at the beginning of a scalar.
Did you try to do:
PRIVATE_KEY: |-
-----BEGIN RSA PRIVATE KEY-----
line2
that would be a key value pair (note the value indicator (:) instead of the normal character =), with the value being a block style literal scalar
Try using > this solution works pretty well if you need to have a json in your env variables. There are many ways to have a multiline strings in YAML.
version: '2'
services:
catalog-api-autoscaling:
image: company.it/project/catalog-api-autoscaling:latest
container_name: api-autoscaling
ports:
- "8083:8083"
environment:
CONFIG_ABC: >
{
"database": {
"catalog": {
"credentials": {
"username": "scott",
"password": "tiger",
"datbase": "catalog",
"host": "gn.dmfkd.lan"
}
}
}
}
CONFIG_DEF: >
{
"urlRegex": "/.*",
"script": {
"scriptPath": "example-python-app.py"
},
"runtime": "python27",
"threadsafe": true,
}
Related
I have this secret built like this:
apiVersion: v1
kind: Secret
metadata:
name: secrets
type: Opaque
stringData:
PORT: "3000"
MONGODB_HOSTNAME: hostname
MONGODB_USER: fares
MONGODB_PASSWORD: password
MONGODB_TEST_HOSTNAME: localhost
ENCODED_CREDENTIALS: ewog...
ENCODED_CREDENTIALS contains an encoded base64 JSON file. It's decoded in the app but I need it to remain encoded as a secret.
Now, I seal it using my cert and kubeseal, but ArgoCD displays this: ErrUnsealFailed - Failed to unseal: illegal base64 data at input byte 4852.
I feel like it's the fact that ENCODED_CREDENTIALS is already encoded that might be a problem, but I'm not sure.
Are you guys familiar with this kind of problems?
TIA
EDIT:
The decoding (pre-seal) works:
echo -n $test_thing | base64 -d
{
"type": "service_account",
"project_id": "blabla",
"private_key_id": "blabla",
"private_key": "-----BEGIN PRIVATE KEY-----
...
\n-----END PRIVATE KEY-----\n",
"client_email": "john.doe#gserviceaccount.com",
"client_id": "abcd1234",
"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/bucket-sa%40steve-jobs.iam.gserviceaccount.com"
}
It's only when it seals & unseals with the sealed secrets controller that it fails.
Good news!
I've managed to find where the issue is.
For some reason, adding an (intentionally) encoded value to stringData keys breaks the unsealing process.
For those who are curious, I've raised the bug (?) to the sealed secrets team: #1038
I have a Laravel(Lumen) Login API, which generates a JWT using HS256. Then I sent my bearer token to Envoy Gateway and get from Envoy
JWT verification fails
On official JWT decode site I could successfully decode and verify my bearer token. Here I generate my JWT:
{
$payload = [
'iss' => config('app.name'), // Issuer vom Token
'sub' => strval($user->ID), // Subject vom Token
'username' => $user->username,
'iat' => time() - 500, // Time when JWT was issued.
'exp' => time() + config('jwt.ttl'), // Expiration time
'alg' => 'HS256',
'kid' => 'ek4Z9ouLmGnCoezntDXMxUwmjzNTBqptKNkfaqc6Ew8'
];
$secretKey = 'helloworld'; //my base64url
$jwtEnc = JWT::encode($payload, $secretKey, $payload['alg'], $payload['kid']);
return $jwtEnc;
}
Here is my Envoy config:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
'#type': 'type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager'
stat_prefix: edge
http_filters:
- name: envoy.filters.http.jwt_authn
typed_config:
"#type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
providers:
provider1:
issuer: 'Lumen'
forward: true
local_jwks:
inline_string: '{"keys": [{"kty": "oct", "use": "sig", "kid": "ek4Z9ouLmGnCoezntDXMxUwmjzNTBqptKNkfaqc6Ew8", "k": "helloworld", "alg": "HS256"}]}' //'k' is here base64url
rules:
- match:
prefix: "/list"
requires:
provider_name: "provider1"
- name: envoy.filters.http.router
route_config:
virtual_hosts:
- name: all_domains
domains: [ "*" ]
routes:
- match:
prefix: "/api"
route:
cluster: loginapi
clusters:
- name: loginapi
connect_timeout: 5s
load_assignment:
cluster_name: loginapi
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 0.0.0.0
port_value: 8080
The token is signed and verified with a symmetric algorithm (HS256).
The key parameters of the symmetric key are provided in form of a JSON Web Key in the local_jwks parameter in the Envoy configuration. The key value itself in the parameter "k" is supposed to be stored in Base64Url format:
The "k" (key value) parameter contains the value of the symmetric (or other single-valued) key. It is represented as the base64url encoding of the octet sequence containing the key value.
(see RFC7518 Section 6.4.1)
Base64Url encoding is used here in order to be able to use binary keys (i.e keys in which every byte can have any value in the full range from 0 to 255) for signing.
When the key is used for signing and verification, it has to be decoded to it's (potentially) binary form.
To stick with the simple example key "helloworld" (of course, just for illustration, not as a real key), this key would have to be stored as "k":"aGVsbG93b3JsZA" (the base64url form of "helloworld") in the inline jwk in the configuration and
used in the not encoded form "helloworld" to sign the token. The receiving side also uses the base64url decoded value of k to verify the signature.
Summary:
create a binary key and base64url encode it
store the encoded key in the "k" parameter of the local_jwks parameter in the Envoy configuration
decode the value of "k" to use it as a key to verify or sign the token
You can use the following website https://base64.guru/standards/base64url/encode to encode base64url.
in "k": tempo-secret base64URL encoded
my working config:
http_filters:
- name: envoy.filters.http.jwt_authn
typed_config:
"#type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
providers:
provider1:
issuer: 'jwt-issuer'
forward: true
local_jwks:
inline_string: '{"keys":[{"kty":"oct","alg":"HS256","k":"dGVtcG8tc2VjcmV0"}]}'
# from_headers:
# - name: authorization
rules:
- match:
prefix: "/"
requires:
Here is the command I used on ubuntu 20.x to generate key pair of EdDSA 25519 for JOSE/NODEJS (14.16) app:
$ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/id-ed25519 -C myemail_address
Here is the private key generated:
-----BEGIN OPENSSH PRIVATE KEY-----
a3BlbnNzaC1rZXktdjEAAAAABG5vbmVAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACAp92w+fwodL4kaUDrNghdZScdcg54IJOO6tLpG91oeKgAAAJj71Y9w+9WP
cAAAAAtzc2gtZWQyNTUxOQAAACAp92w+awodL4kaUDrNghdZScdcg54IJOO6tLpG91oeKg
AAAEDsEfbdyx4HaM5cL1f2Ag2Knb0NDCIiuIDsm6FwR5NJESn3bD5/Ch0viRpQOs2CF1lJ
c1yDnggk47q0ukb3Wh4qAAAAFGVtY2yhYjIwMTFAZ21haWwuY29tAQ==
-----END OPENSSH PRIVATE KEY-----
The private key has 366 bytes instead of 32 bytes.
Here is the public key:
BAAAC3NzaC1lZ1I1NTE5AAAAICn3CD5/Ch0viRpQOs2CF1lJx1yDnggk47q0ukb3Wh4q myemail_address
It is 63bytes without counting email address and seems too long.
Is it the right way to generate key pair for EdDSA 25519? If it is not, what is the right way?
You can use Node.js (>= 12.0.0) for this as well.
const keypair = crypto.generateKeyPairSync(
'ed25519',
{
privateKeyEncoding: { format: 'pem', type: 'pkcs8' },
publicKeyEncoding: { format: 'pem', type: 'spki' }
}
)
console.log(keypair.privateKey)
console.log(keypair.publicKey)
There is both blocking and non-blocking API for this.
I have Google's Identity-Aware Proxy configured for my JupyterHub application, and would like to use it to authenticate my users. How do I accomplish this?
Google passes signed JWT headers to applications with IAP in front of them, as described in Securing your app with signed headers. You can use mogthesprog/jwtauthenticator to enable JWT-based authentication in JupyterHub.
Configuring through jupyterhub_config.py
Once jupyterhub-jwtauthenticator is installed on your JupyterHub server, add the following configuration:
jupyterhub_config.py
c.JupyterHub.authenticator_class = 'jwtauthenticator.jwtauthenticator.JSONWebTokenAuthenticator'
c.JSONWebTokenAuthenticator.header_name = 'x-goog-iap-jwt-assertion'
c.JSONWebTokenAuthenticator.header_is_authorization = False
c.JSONWebTokenAuthenticator.expected_audience = '/projects/PROJECT_NUMBER/global/backendServices/SERVICE_ID`
c.JSONWebTokenAuthenticator.username_claim_field = 'email'
# Retrieved from https://www.gstatic.com/iap/verify/public_key
c.JSONWebTokenAuthenticator.secret = """
{
"2nMJtw" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9e1x7YRZg53A5zIJ0p2ZQ9yTrgPL\nGIf4ntOk+4O2R2+ryIObueyenPXE92tYG1NlKjDNyJLc7tsxi0UUnyxpig==\n-----END PUBLIC KEY-----\n",
"6BEeoA" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElmi1hJdqtbvdX1INOf5B9dWvkydY\noowHUXiw8ELWzk/YHESNr8vXQoyOuLOEtLZeCQbFkeLUqxYp1sTArKNu/A==\n-----END PUBLIC KEY-----\n",
"FAWt5w" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8auUAdTS54HmUuIabrTKvWawxmbs\n81kdbzQMV/Tae0EhLgin8qnJ4lklJrxEzksXg5OtBuzE62DIj+CePN20Pg==\n-----END PUBLIC KEY-----\n",
"LYyP2g" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESlXFFkJ3JxMsXyXNrqzE3ozl/091\n3PmNbccLLWfeQFUYtJqGtl8ESuYxRwc/QwZp5Wcl0HCq6GuFDx4/Tk18Ig==\n-----END PUBLIC KEY-----\n",
"f9R3yg" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESqCmEwytkqG6tL6a2GTQGmSNI4jH\nYo5MeDUs7DpETVhCXXLIFrLg2sZvNqw8SGnnonLoeqgOSqRdjJBGt4I6jQ==\n-----END PUBLIC KEY-----\n"
}
"""
Configuring through zero-to-jupyterhub-k8s
If you're using zero-to-jupyterhub-k8s to provision JupyterHub in a Kubernetes cluster, you will first need to bake the jupyterhub-jwtauthenticator package into your hub image.
With the following Dockerfile and cloudbuild.yaml in a directory, execute gcloud builds submit --config cloudbuild.yaml . using the appropriate project.
Dockerfile
FROM jupyterhub/k8s-hub:0.7.0
RUN pip3 install --no-cache-dir jupyterhub-jwtauthenticator
cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/docker'
args: [ 'pull', 'docker.io/jupyterhub/k8s-hub:0.7.0' ]
- name: 'gcr.io/cloud-builders/docker'
args: [ 'build', '-t', 'gcr.io/$PROJECT_ID/k8s-hub', '.' ]
images:
- 'gcr.io/$PROJECT_ID/k8s-hub'
values.yaml
hub:
image:
name: gcr.io/<project>/k8s-hub
tag: latest
auth:
type: custom
custom:
className: 'jwtauthenticator.jwtauthenticator.JSONWebTokenAuthenticator'
config:
header_name: x-goog-iap-jwt-assertion
header_is_authorization: false
expected_audience: '/projects/PROJECT_NUMBER/global/backendServices/SERVICE_ID'
username_claim_field: email
# Retrieved from https://www.gstatic.com/iap/verify/public_key
secret: |
{
"2nMJtw" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9e1x7YRZg53A5zIJ0p2ZQ9yTrgPL\nGIf4ntOk+4O2R2+ryIObueyenPXE92tYG1NlKjDNyJLc7tsxi0UUnyxpig==\n-----END PUBLIC KEY-----\n",
"6BEeoA" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElmi1hJdqtbvdX1INOf5B9dWvkydY\noowHUXiw8ELWzk/YHESNr8vXQoyOuLOEtLZeCQbFkeLUqxYp1sTArKNu/A==\n-----END PUBLIC KEY-----\n",
"FAWt5w" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8auUAdTS54HmUuIabrTKvWawxmbs\n81kdbzQMV/Tae0EhLgin8qnJ4lklJrxEzksXg5OtBuzE62DIj+CePN20Pg==\n-----END PUBLIC KEY-----\n",
"LYyP2g" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESlXFFkJ3JxMsXyXNrqzE3ozl/091\n3PmNbccLLWfeQFUYtJqGtl8ESuYxRwc/QwZp5Wcl0HCq6GuFDx4/Tk18Ig==\n-----END PUBLIC KEY-----\n",
"f9R3yg" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESqCmEwytkqG6tL6a2GTQGmSNI4jH\nYo5MeDUs7DpETVhCXXLIFrLg2sZvNqw8SGnnonLoeqgOSqRdjJBGt4I6jQ==\n-----END PUBLIC KEY-----\n"
}
Retrieving IAP public keys automatically
If you don't want to bake the public keys for IAP JWT tokens into your configuration, you can retrieve these at run-time through your jupyterhub_config.py, or as extraConfig in the helm chart.
jupyterhub_config.py
from urllib import request
c.JSONWebTokenLocalAuthenticator.secret = request.urlopen('https://www.gstatic.com/iap/verify/public_key').read()
For zero-to-jupyterhub-k8s:
values.yaml
hub:
extraConfig:
config-jwtauthenticator: |
from urllib import request
c.JSONWebTokenLocalAuthenticator.secret = request.urlopen('https://www.gstatic.com/iap/verify/public_key').read()
Hi I am testing some api through POSTMAN.
REGISTRATION API- It takes public key and stores in server.To get public JWK Key I am using https://mkjwk.org/. It generates a key with public and private key. Below is the key generated:
{
"kty": "RSA",
"d": "HgP6c8xA3D_-8DKgSk3fQ_FZuPj2RNSFE5NLfGz3GJjkyt9fzOPztNObQmLZ2EoJzPrYL8ljk-1mKGIr5Ma1n4TPX_kQ9JErq9wNyhMUTykQ8PqjMuxmUpddn43RZ27VPjvUvHMulk5hPBFv0uH3LnDsM1xn34icj40y4zcRTYXwixqDgj74Ua_9aaZwPXX06Ykc3vzC5M4F5JP4ZjuLTFjmM8jxzJpu4JNDncXwhHE5Xtv3t1oezXTHNZdRzyTTtFLOeyYeLt5WWM-y549du3hsUtvgNnJ4JTS4uEHEonDMW8CV5ZzoQE8F81LT5Q84coYzOjVlzC50w7st3vLFYQ",
"e": "AQAB",
"use": "sig",
"kid": "sdk291",
"alg": "RS256",
"n": "0h5Pgw32t3NtODVj1UrNkk90RytZBz2T09JBEo1NwYtw0T7NM3SrFsleLK8e_DknE26rB8EXD2T1YmUSuseuWvW-LPdwbk--SrKo8Df1H5ff5hDZYJ_x-NPDJ_ZmoY7r2U83aGY-DubilufhDf6icB2auTGxBvVylAl5Jdf7UBsjHAWrgWAtFFvnkbcaUk1O7ZA8nS4Iyk4l8vVsoUOJCSRrysceObAOG-EYj1UfdzOBZsuSj5Usst6ebRjF9M1VNJOLcvm6EiAqazayyqbsengnA-hqUGRgfd6HXXZ5Hg4BU_srPVBXrVmx81azHY5lRUdZr_Khtw4O0Zy3UIwMWw"
}
I am only sending public key portion to this API and this API Works fine.
GETTING ACCESS TOKEN USING JWT API- This takes a JWT which will be created with some claims . And we have to sign it with RSA Public and private key. I am facing problem in signing the JWT.
To get text/pem version of public and private keys from above JWK, I am using https://8gwifi.org/jwkconvertfunctions.jsp . This gives us below public and private key.
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0h5Pgw32t3NtODVj1UrN
kk90RytZBz2T09JBEo1NwYtw0T7NM3SrFsleLK8e/DknE26rB8EXD2T1YmUSuseu
WvW+LPdwbk++SrKo8Df1H5ff5hDZYJ/x+NPDJ/ZmoY7r2U83aGY+DubilufhDf6i
cB2auTGxBvVylAl5Jdf7UBsjHAWrgWAtFFvnkbcaUk1O7ZA8nS4Iyk4l8vVsoUOJ
CSRrysceObAOG+EYj1UfdzOBZsuSj5Usst6ebRjF9M1VNJOLcvm6EiAqazayyqbs
engnA+hqUGRgfd6HXXZ5Hg4BU/srPVBXrVmx81azHY5lRUdZr/Khtw4O0Zy3UIwM
WwIDAQAB
-----END PUBLIC KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICHgIBAAKCAQEA0h5Pgw32t3NtODVj1UrNkk90RytZBz2T09JBEo1NwYtw0T7N
M3SrFsleLK8e/DknE26rB8EXD2T1YmUSuseuWvW+LPdwbk++SrKo8Df1H5ff5hDZ
YJ/x+NPDJ/ZmoY7r2U83aGY+DubilufhDf6icB2auTGxBvVylAl5Jdf7UBsjHAWr
gWAtFFvnkbcaUk1O7ZA8nS4Iyk4l8vVsoUOJCSRrysceObAOG+EYj1UfdzOBZsuS
j5Usst6ebRjF9M1VNJOLcvm6EiAqazayyqbsengnA+hqUGRgfd6HXXZ5Hg4BU/sr
PVBXrVmx81azHY5lRUdZr/Khtw4O0Zy3UIwMWwIBAAKCAQAeA/pzzEDcP/7wMqBK
Td9D8Vm4+PZE1IUTk0t8bPcYmOTK31/M4/O005tCYtnYSgnM+tgvyWOT7WYoYivk
xrWfhM9f+RD0kSur3A3KExRPKRDw+qMy7GZSl12fjdFnbtU+O9S8cy6WTmE8EW/S
4fcucOwzXGffiJyPjTLjNxFNhfCLGoOCPvhRr/1ppnA9dfTpiRze/MLkzgXkk/hm
O4tMWOYzyPHMmm7gk0OdxfCEcTle2/e3Wh7NdMc1l1HPJNO0Us57Jh4u3lZYz7Ln
j127eGxS2+A2cnglNLi4QcSicMxbwJXlnOhATwXzUtPlDzhyhjM6NWXMLnTDuy3e
8sVhAgEAAgEAAgEAAgEAAgEA
-----END RSA PRIVATE KEY-----
I am taking these keys and going to https://jwt.io/ , then updating Header and payload with my required values.
Header:
{
"alg": "RS256",
"typ": "JWT"
}
Payload :
{
"iss": "e9064e3cb1cc445cb2095f3dc675b4gf",
"sub": "e9064e3cb1cc445cb2095f3dc675b4gf",
"aud": [
"southgate"
],
"iat": 1543469348,
"nbf": 1543469348,
"exp": 1543517174,
"jti": "a6fb0873-8653-4923-be47-e53e0acabb35",
"schemas": [
"urn:x:y:v1"
],
"ten": "myTen"
}
After this when I sign the JWT including public and private key from above, It doesnt generate JWT token and gives "INVALID SIGNATURE" error. SO I am not able to generate the signed JWT which is needed as input for this 2nd API.
PS- I am in testing phase now. So I havent wrote any code to test the api and using only online generator tool.
Please let me know how I can solve the issue.