VaultSharp AppRole Login Unwrapping problem - hashicorp-vault

I logged in via the CLI using my standard Token obtained from the UI. Then I ran this to get a wrapping token:
vault write auth/approle/login role_id="e309ea24-994c-771e-939f-49e24a936ef2" secret_id="9597c7d0-3a88-c8f7-e43f-e8999600e38e"
that call returned:
Key Value
--- -----
token s.5NuuJxEfdiJrfSiXXCU5MjZ6.dYgGw
token_accessor 3JFGpuaO45DuxD9nd6mUL6ic.dYgGw
token_duration 1h
token_renewable true
token_policies ["default" "transaction"]
identity_policies []
policies ["default" "transaction"]
token_meta_role_name transaction
Now, I used the token in an unwrapping call like this:
IVaultClient vaultClientForUnwrapping = new VaultClient(
new VaultClientSettings(_settings.Address, new TokenAuthMethodInfo(vaultToken: wrappingToken))
);
string appRoleAuthSecretId
= vaultClientForUnwrapping.V1.System
.UnwrapWrappedResponseDataAsync<Dictionary<string, object>>(tokenId: null)
.Result.Data["secret_id"]
.ToString();
And when attempting to run the Unwrapping call above, I get this exception:
One or more errors occurred. ({"errors":["wrapping token is not valid or does not exist"]}
Can anyone help out here?

The call vault write auth/approle/login role_id="e309ea24-994c-771e-939f-49e24a936ef2" secret_id="9597c7d0-3a88-c8f7-e43f-e8999600e38e" is not returning a wrapped token, but instead a raw token.
Essentially, in order to get a wrapped token, you need to provide the -wrap-ttl flag.
#!/usr/bin/env bash
vault server -dev -dev-root-token-id=root -dev-listen-address=127.0.0.1:8200 &
VAULT_SERVER_PID=$!
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=root
vault auth enable approle
vault write auth/approle/role/test-role policies=default
ROLE_ID=$(vault read -format=json auth/approle/role/test-role/role-id | jq -r .data.role_id)
SECRET_ID=$(vault write -f -format=json auth/approle/role/test-role/secret-id | jq -r .data.secret_id)
VAULT_WRAP_TOKEN=$(vault write -wrap-ttl=1h -format=json auth/approle/login role_id=${ROLE_ID} secret_id=${SECRET_ID} | jq -r .wrap_info.token)
VAULT_TOKEN=${VAULT_WRAP_TOKEN} vault write -f sys/wrapping/unwrap
kill -9 ${VAULT_SERVER_PID}
This is a sample script that would provide an actual wrapped token, and the process for unwrapping it. You can add the -output-curl-string flag to any of the vault commands above to see what the API commands might be. I've used jq for the programmatic passing of IDs to the next commands, but you can omit the -format=json and trailing | jq -r ... if you wish to see the table-formatted responses from the vault binary.
The reason that most libraries that require Vault Tokens do the wrapping step is so that it can be certain that nothing except the end user of the token has ever seen the token. A wrapping token can only be used once, and so ensures that nothing else has unwrapped the token before being used.
However, in the case of VaultSharp, a casual glance suggests that you can pass the Role ID and Secret ID directly to the library and have it generate its own tokens on demand. You may wish to look into this instead.

Related

Error when try apply configmap to auth with EKS cluster

i have the follow question. i try connect to eks cluster using a Terraform with Gitlab CI/CD , i receive the error message , but when try it in my compute , this error dont appear, someone had same error ?
$ terraform output authconfig > authconfig.yaml
$ cat authconfig.yaml
<<EOT
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: "arn:aws:iam::503655390180:role/clusters-production-workers"
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
EOT
$ kubectl create -f authconfig.yaml -n kube-system
error: error parsing authconfig.yaml: error converting YAML to JSON: yaml: line 2: mapping values are not allowed in this context
The output is including EOT(EndOfText) marks since it is generated as a multiline string originally.
as documentation suggests (terrafom doc link)
Don't use "heredoc" strings to generate JSON or YAML. Instead, use the
jsonencode function or the yamlencode function so that Terraform can
be responsible for guaranteeing valid JSON or YAML syntax.
use json encoding or yaml encoding before building output.
If you want to continue like this with what you have now then try to give these options with output -json or -raw
terraform output -json authconfig > authconfig.yaml
or
terraform output -raw authconfig > authconfig.yaml
The error message tells you the authconfig.yaml file can not be converted from YAML to JSON, suggesting it's not a valid yaml
The cat authconfig.yaml you're showing us includes some <<EOT and EOT tags. I would suggest to remove those, before running kubectl create -f
Your comment suggests you knew this already - then why didn't you ask about terraform, rather than showing us kubectl create failing? From your post, it really sounded like you copy/pasted the output of your job, without even reading it.
So, obviously, the next step is to terraform output -raw, or -json, there are several mentions in their docs, or knowledge base, a google search would point you to:
https://discuss.hashicorp.com/t/terraform-outputs-with-heredoc-syntax-leaves-eot-in-file/18584/7
https://www.terraform.io/docs/cli/commands/output.html
Last: we could ask why? Why would you terraform output > something, when you can have terraform write a file?
While as a general rule, whenever writing terraform stdout/stderr to files, I strongly suggest going with no-color.

Open api generator : change Client name

I am using the "OpenApi generator" to create the client library for an api.
openapi-generator generate -i https://xxxx.cloudfront.net/openapi/en-us/product/2-0/openapi.yaml -g ruby -o tmp/test/custom_name
This generate a class "OpenapiClient" but I need to change this name to "CustomApiClient". How can I pass this value?
This seems to me a standard thing to do, why is not so immediate? Am I following the best practice?
# Load the gem
require 'openapi_client'
# Setup authorization
OpenapiClient.configure do |config|
# Configure Bearer authorization: bearer
config.access_token = 'YOUR_BEARER_TOKEN'
end
This seemed way harder to find than it should have been, but if you run openapi-generator config-help -g ruby, it will show you all the options for ruby client configurations. Specifically, gemName. So you can simply create a config file like:
# config.yaml
gemName: custom_api_client
and provide -c /path/to/your/config.yaml when running the generate command.

Kubectl create multiline secret

I'm trying to put a Service Account into a secret - I did it previously a year ago and it works but now - no matter how I approach it, the application doesn't see it right and says there is Input byte array has incorrect ending byte - When creating normal secret I know you've gotta do it with a new line so
echo -n "secret" | base64
and put that value in secret and apply, but my multiline file
cat secret.json
{
"type": "service_account",
"project_id": "smth-smth",
"private_key_id": "blabla"
...
}
No matter how I approach - whether put it by hand like in the first example, or do it with
cat secret.json | base64
# or
base64 < secret.json
the secret is created but application throws
Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Input byte array has incorrect ending byte at 3104
When I compare the new secret to the last one of the service account the difference is how the output looks like
The working one is smth like this - when I try to decrypt the base64
echo -n "<long string of base64 encrypred sa> | base64 -D
{ "type": "service_account", "project_id": "blabla"... }
so it's in one line, and the new SA I try to decrypt is outputed in the format as in the file - so each part of json in new line - I tried manually putting it all in one line but without success
Anyone know ? how to put a multiline file in a secret (base64) properly?
The easiest way to create a secret from a file is to use kubectl create secret generic.
Put your file secret.json in a folder config and then run:
kubectl create secret generic my-secret --from-file=config
You will get a secret my-secret with one key secret.json containing your file (which you can then mount to a pod volume).
If you cannot create files an option is to write into a variable and then load the result into a --file-literal. This may be necessary because it seems kubectl either escapes newline characters \n when inside a quoted string and ignores them if no quotes are supplied. When reading from a variable the \nare treated as expected.
EDIT: With regards to multi-line strings do take care to use correct linefeed characters, as explained here. I ran into that when trying my answer at home :)
target_string=$(echo "string1\nstring2")
kubectl create secret generic your-secret-name --from-literal=your_key=$target_string

Pub/Sub notification for GCS - event filter doesn't work

What I wanted is whenever (and only when) a file is created on GCS, my pub/sub subscription can receive a notification.
So I did this:
gsutil notification create -t projects/[my-project-id]/topics/new-raw-file -f none -m eventType:OBJECT_FINALIZE gs://[the-target-bucket]
I think this config is set up successfully, because when I ran gsutil notification list , it shows:
projects/_/buckets/[the-target-bucket]/notificationConfigs/7
Cloud Pub/Sub topic: projects/[my-project-id]/topics/new-raw-file
Custom attributes:
eventType: OBJECT_FINALIZE
This is the only config.
However, other than file creation, I also receive file deletion notification:
Received 1 messages.
* 118758642722910: message - , attributes - {u'resource': u'projects/_/buckets/[the-target-bucket]/objects/2466870.3.txt#1493038968423735', u'objectId': u'2466870.3.txt', u'bucketId': u'[the-target-bucket]', u'notificationConfig': u'projects/_/buckets/[the-target-bucket]/notificationConfigs/7', u'payloadFormat': u'NONE', u'eventType': u'OBJECT_DELETE', u'objectGeneration': u'1493038968423735'}
didn't get what was going wrong.
Turns out I misused one command option. According to this page, "-m" actually just append a key:value attribute to the notification, it has nothing to do with the event filter that I wanted. The right option to use should be "-e" . So, the following config command actually works properly:enter code here
gsutil notification create -t [TOPIC_NAME] -f json -e OBJECT_FINALIZE gs://[BUCKET_NAME]

Bash/Curl example of pocket oAuth login

I'm trying to get a simple bash script working with the pocket api. All I want to do is authenticate with pocket and download my list of articles (actually, only the count)
I'm a little confused by the way that the oauth process works.
I've registered my app with the pocket api and have a consumer key
its marked as in "development" - I'm not sure if this is important.
The bit that's confusing me is that it seems that the way that the oAuth flow works with it's redirect uris is that it only really works with a gui (i.e a browser) - is it possible to do this with a bash script?
Here is what I have below. it works up until I have the TOKEN, but then I'm not sure what to do next.
#!/bin/bash
REDIR="redirect_uri=pocketapp1234:authorizationFinished"
KEY=21004-xxxxxxabcabcabc # you can assume this is the consumer key pocket issues for my app.
CODE=`curl -X POST --data "consumer_key=$KEY&$REDIR" https://getpocket.com/v3/oauth/request`
echo "OK - code is $CODE"
TOKEN=$(echo $CODE | awk -F"=" '{print $2}')
echo "OK - token is $TOKEN"
AUTH="consumer_key=$KEY&$CODE"
# This line seems not to work
curl -v "https://getpocket.com/auth/authorize?request_token=$TOKEN&$REDIR"
Yes, the browser portion is required. At the authorize phase, there is a page from getpocket.com prompting the user to login and authorise the bash script to access the user's Pocket account.
You can refer to Step 3 of the Pocket API Docs.
This is the Python v3.8 script I'm using and seems to work.
#!/usr/bin/env python
from os import environ as env
import requests
import webbrowser
def authorize_pocket_app():
data = {
"consumer_key": env['POCKET_CONSUMER_KEY'],
"redirect_uri": env['POCKET_APP_NAME'],
}
resp = requests.post(url="https://getpocket.com/v3/oauth/request", data=data)
code = resp.text.split("=")[1]
webbrowser.open(f"https://getpocket.com/auth/authorize?request_token={code}"
"&redirect_uri=https://duckduckgo.com")
input("Authorize %s app in the browser, then click enter" % env['POCKET_APP_NAME'])
get_token(code)
def get_token(code):
resp = requests.post(
url="https://getpocket.com/v3/oauth/authorize",
data={
"consumer_key": env["POCKET_CONSUMER_KEY"],
"code": code,
})
token = resp.text.split("&")[0].split("=")[1]
print("Secret token:", token)
if __name__ == "__main__":
authorize_pocket_app()
To use it as is you need to install requests external library and export POCKET_CONSUMER_KEY and POCKET_APP_NAME in your shell environment. E.g.
pip install requests
export POCKET_CONSUMER_KEY=xxx-yyy-zzz
export POCKET_APP_NAME=my-pocket-app
python <filename>.py
HTH