AWS CDK Secrets Manager can't find the specified secret - aws-cdk

In our project, we store all secrets in us-east-1 region (in the secrets manager). Now, we are deploying a new CDK project to us-west-2 region, this project should use the secrets from us-east-1 by fully specified secret ARN.
Example:
import * as secretsManager from 'aws-cdk-lib/aws-secretsmanager';
...
const mongoDbCredentials = secretsManager.Secret.fromSecretAttributes(this, id, {
secretCompleteArn: props.config.mongoDb.credentials.arn,
});
Problem:
This error happens in attempt to deploy new project:
"Secrets Manager can't find the specified secret. (Service: AWSSecretsManager; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: 918e74b7-bef8-4b6c-b8c0-f9c901037806; Proxy: null)"
Expected result:
We expect the new project will be successfully deployed with secrets from another region.

Related

How to pass in AWS environmental variables to Nextflow for use in Docker container

I would like to run a Nextflow pipeline through a Docker container. As part of the pipeline I would like to push and pull from AWS. To accomplish this end, I need to pass in AWS credentials to the container, but I do not want to write them into the image.
Nextflow has an option to pass in environmental variables as part of the Docker scope via the envWhitelist option, however I have not been able to find an example for correct syntax when doing this.
I have tried the following syntax and get an access denied error, suggesting that I am not passing in the variables properly.
docker {
enabled = true
envWhitelist = "AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID"
}
I explicitly passed these variables into my environment and I can see them using printenv.
Does this syntax seem correct? Thanks for any help!
Usually you can just keep your AWS security credentials in a file called ~/.aws/credentials:
If AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are not defined in the
environment, Nextflow will attempt to retrieve credentials from your
~/.aws/credentials or ~/.aws/config files.
Alternatively, you can declare your AWS credentials in your nextflow.config (or in a separate config profile) using the aws scope:
aws {
accessKey = '<YOUR S3 ACCESS KEY>'
secretKey = '<YOUR S3 SECRET KEY>'
region = '<REGION IDENTIFIER>'
}
You could also use an IAM Instance Role to provide your credentials.

create jenkins ssh username with private key credential via rest xml api

Basically, I am trying to create a credential on jenkins via Rest API. Using xml data below:
<?xml version='1.0' encoding='UTF-8'?>
<com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
<scope>GLOBAL</scope>
<id>jenkins-github-ssh</id>
<description>jenkins-github-ssh</description>
<username>username</username>
<directEntryPrivateKeySource>
<privateKey>-----BEGIN OPENSSH PRIVATE KEY-----
*****************************************
-----END OPENSSH PRIVATE KEY-----</privateKey>
</directEntryPrivateKeySource>
</com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
I can see the credential after calling REST post request. But when I use this credential for a GitHub repository, Jenkins says:
Failed to connect to repository : Command "git ls-remote -h -- git#github.com:***.git HEAD" returned status code 128:
stdout:
stderr: Load key "/tmp/ssh3978703187838467164.key": invalid format
git#github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
But If I update the credential which is created by rest api with same private key above manually. It works. Somehow key is broken while posting. Do you guys have any idea to point me the solution?
Jenkins 2.198 & SSH Credentials Plugin 1.17.3
Thanks
I faced exactly the same problem while pushing private SSH keys to Jenkins by a Python script. I'm using the Requests library to create and update SSH key credential sets in arbitrary credential stores on the Jenkins server.
The general problem is that your XML structure is partially wrong. The tag
<directEntryPrivateKeySource>
must be replaced by
<privateKeySource class="com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource">
Getting the basic XML structure
You can get the correct XML structure by yourself from the Jenkins server when you follow these steps:
Create a SSH key credential item manually. In the example below the key's id is test-sshkey. Let's place it in a credential store which is located in the folder "API-Test" which is a subfolder of "Playground", i.e. Playground/API-Test.
When you click on the newly created credential item in the Jenkins UI its URL should look like this:
https://JENKINS_HOSTNAME/job/Playground/job/API-Test/credentials/store/folder/domain/_/credential/test-sshkey/
Add /config.xml to the URL above so that it looks like this:
https://JENKINS_HOSTNAME/job/Playground/job/API-Test/credentials/store/folder/domain/_/credential/test-sshkey/config.xml
The XML structure returned by the URL in step 3 has almost the structure that we need for using with the Credentials API but is partially incomplete:
<com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey plugin="ssh-credentials#1.18.1">
<id>test-sshkey</id>
<description>DELETE AFTER USE</description>
<username>test</username>
<privateKeySource class="com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource">
<privateKey>
<secret-redacted/>
</privateKey>
</privateKeySource>
</com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
Using the Credentials API
Add the tags <scope> and <passphrase> for a valid XML scaffold that you can POST to the Credentials API:
<com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
<scope>GLOBAL</scope>
<id>CREDENTIAL_ID</id>
<description>MY_DESCRIPTION</description>
<username>A_USERNAME</username>
<passphrase>OPTIONAL_KEY_PASSWORD</passphrase>
<privateKeySource class="com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource">
<privateKey>YOUR_PRIVATE_SSH_KEY_GOES_HERE</privateKey>
</privateKeySource>
</com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
Caveat: If the submitted XML has a wrong structure the REST API of the Credentials Plugin will nevertheless accept it and return a misleading HTTP status code 200!
Now we can use this XML structure to POST it to the API endpoints for creating or updating by cURL or similar tools. We assume that all operations are executed in the credential store of the folder "Playground/API-Test".
The following code example in Python is "dumbed down" completely to focus on the general approach:
def addCredentialSetSshPrivateKey(self, credentialDataObj):
"""
Adds a credential set with a private SSH key to a credential store
credentialDataObj: An instance of a simple DTO
"""
jenkinsRequestUrl = "https://ci-yoda-new.codemanufaktur.com/job/Playground/job/API-Test/credentials/store/folder/domain/_/createCredentials"
authentication = ("jenkins_admin_user", "API-TOKEN_FOR_THE_USER")
completeSamlData = """
<com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
<scope>GLOBAL</scope>
<id>{0}</id>
<description>{1}</description>
<username>{2}</username>
<passphrase>{3}</passphrase>
<privateKeySource class="com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey$DirectEntryPrivateKeySource">
<privateKey>{4}</privateKey>
</privateKeySource>
</com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
""".format(credentialDataObj.id(), credentialDataObj.description(), credentialDataObj.username(), credentialDataObj.key_passphrase(), credentialDataObj.private_ssh_key())
# When using CSRF protection in Jenkins a API crumb must be included in the actual REST call.
# The following method requests the Jenkins Crumb Issuer for a API crumb and returns a JSON object like this:
# {'_class': 'hudson.security.csrf.DefaultCrumbIssuer', 'crumb': 'a5d36ef09e063322169888f0b81341fe13b4109482a7936bc08c6f9a01badd39', 'crumbRequestField': 'Jenkins-Crumb'}
jsonCrumb = self._requestApiCrumb()
# The actual REST call with headers, XML payload and all other bells and whistles.
remoteSession = requests.Session()
return remoteSession.post(jenkinsRequestUrl, auth = authentication, headers = {"content-type":"application/xml", jsonCrumb['crumbRequestField']:jsonCrumb['crumb']}, data = completeSamlData)
REST endpoint for creating a SSH credential item:
https://JENKINS_HOSTNAME/job/Playground/job/API-Test/credentials/store/folder/domain/_/createCredentials
REST endpoint for updating a SSH credential item:
https://ci-yoda-new.codemanufaktur.com/job/Playground/job/API-Test/credentials/store/folder/domain/_/credential/credential_ci-yoda-new-project-apex_privatekey/config.xml
Apparently in the latter case you just update the config.xml file of an existing credential item.
Also see the user guide for the Credentials Plugin, section REST API, expecially for constructing the correct REST URLs. For requesting the Jenkins crumb issuer with Python see this StackOverflow answer.
Solution tested with:
Jenkins 2.214
Credentials Plugin 2.3.1
SSH Credentials Plugin 1.18.1
For the people who are having the exact same problem;
I've tried uploading it as a file, uploading it with API, using jenkins CLI, etc. Everything I tried has failed. Same issue is alsoposted in here;
https://issues.jenkins.io/browse/JENKINS-60714
So steps that finally worked is explained as follows;
Install and configure the Jenkins Configuration as Code Plugin.
Upload your configuration similar to yaml file below.
You might also want to define the private key content as an environment variable in the Jenkins instance and use it as "${private_key}" instead of pasting it visibly.
jenkins:
systemMessage: "Example of configuring credentials in Jenkins"
credentials:
system:
domainCredentials:
- credentials:
- basicSSHUserPrivateKey:
description: "kro"
id: "kro"
scope: GLOBAL
username: "kro"
privateKeySource:
directEntry:
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
MIIG5AIBAAKCAYEAvuiaIDs+ydzR7Xxo5Owvv+G9/arbqN0YwhaGQQlicJjM4ZvI
..........YOUR KEY.............
53Zg4QmSb1XGKUTXxIeGd27OIvgkwAn7K/cjQsU9t802iYV3tisnfA==
-----END RSA PRIVATE KEY-----

Serverless offline not taking environment variables

I am new to serverless and would like your help to figure out what I am doing wrong.
In my local development after using sls offline --config cusom.yml i am unable to retrieve secrets. After a bit of debugging, found out that the credentials is null.
However, when i invoke it separately using pure js aws-sdk (not with serverless) I am able to retrieve the secrets and the credentials is prepopulated. Please let me know if you have any suggestions on why this is not working with sls offline
Do you have the following files locally?
~/.aws/credentials
~/.aws/config
These files serves as the credentials if you don't write them in your code. Most libraries and aws cli relies on them for access
$ cat ~/.aws/credentials
[default]
aws_secret_access_key = your_aws_secret_access_key
aws_access_key_id = your_aws_access_key_id
$ cat ~/.aws/config
[default]
region = us-east-1 # or your preferred region

AWS (ResourceNotFoundException) when calling the GetSecretValue operation: Secrets Manager can't find the specified secret

Having ResourceNotFoundException when using secrets ARN
Tried getting secret only using secret name - doesn't work.
Tried getting secret using ARN - doesn't work.
I've checked my assumed role's policy and SM is set as far as I understand like this in the JSON format "secretsmanager:*"
The command I'm using in a CloudBees job is this:
aws secretsmanager get-secret-value --secret-id <ARN>
Not sure what is the issue at the moment. All help appreciated!
Dave
There is not enough information here to tell for sure what the problem is. However, the command line you have does not specify a region and you may be defaulting to the wrong region. Pass --region REGION to the CLI (where REGION is the real region name; e.g. us-east-1) and make sure REGION is the same as the region in the ARN.
I ran into this one as well, my issue was the id was wrong.
aws secretsmanager get-secret-value --secret-id <ARN>
The ARN actually needed to be the secret name.
You may have a secret resource without any secret value configured
You can verify that the secret resource exists using -
aws secretsmanager describe-secret --secret-id <ARN or NAME>
Quoted from AWS CLI aws secretsmanager command documentation:
--secret-id (string)
The ARN or name of the secret to add a new version to.
For an ARN, we recommend that you specify a complete ARN rather than a
partial ARN.
In case you receive the secret resource details you may need to set a secret value using the command:
aws secretsmanager put-secret-value --secret-id <ARN or NAME> --secret-string '[{"user":"username"},{"pass":"password"}]'
And after the secret resource value is set you should be able to use get-secret-value command

use gcloud with Jenkins

I've been trying to write a script that polls Google Cloud Storage periodically. This works fine when I run it normally, but if I include it as a build step in Jenkins, it gives a 403 Forbidden error. This is because there's no gcloud auth login process completed for the Jenkins user, which requires a verification code to be copied..how do I do that using Jenkins ?
EDIT:
I tried the steps at: https://cloud.google.com/storage/docs/authentication#service_accounts and downloaded a JSON key that looks like:
{"web":{"auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","client_email":"....#project.googleusercontent.com","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/....#project.googleusercontent.com","client_id":"....project.googleusercontent.com","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs"}}
which is darn strange because all of the links point to stuff like bad request, invalid request..I must be doing something wrong. The command I ran was:
gcloud auth activate-service-account ...#project.googleusercontent.com --key-file /var/lib/jenkins/....project.googleusercontent.com.json
Your best bet is probably to use a "service account" to authenticate gcloud/gsutil with the GCS service. The major steps are to use generate a JSON-formated private key following the instructions here:
https://cloud.google.com/storage/docs/authentication#service_accounts
Copy that key to a place where the Jenkins user can read it, and as the Jenkins user run
gcloud auth activate-service-account ...
(See https://cloud.google.com/storage/docs/authentication#service_accounts). Note that support for JSON key files is pretty new and you'll need an up-to-date gcloud release.
From there your Jenkins process should be able to access GCS as usual.
The key file should have the following format:
{
"private_key_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"private_key": "-----BEGIN PRIVATE KEY-----\n ... \n-----END PRIVATE KEY-----\n",
"client_email": "...#developer.gserviceaccount.com",
"client_id": "..."
"type": "service_account"
}

Resources