Using Firebase OpenID Connect provider as AWS IAM Identity Provider - amazon-web-services

I get the following error while setting up Firebase as an AWS IAM Identity Provider using OpenID Connect.
We encountered the following errors while processing your request:
Please check .well-known/openid-configuration of provider:
https://securetoken.google.com/<Project ID> is valid.
The AWS IAM Identity Provider setup requires two input parameters, to which I plugged in the following:
Provider URL: https://securetoken.google.com/<Firebase Project ID>
Audience: <Firebase Client ID>
To troubleshoot the error, I opened http://<Provider URL>/.well-known/openid-configuration in a browser and noted the JSON response has the Issuer and jwks_uri fields. I believe these JSON fields indicate the Firebase OpenID Connect Provider URL is valid.
Any idea how I could avoid the above error and successfully set up the AWS IAM Identity Provider?

I contacted AWS support and they helped resolve the problem. Thanks to Shaun H # AWS!
The solution to the problem is to use AWS CLI instead of AWS console to set up an OIDC provider.
I'm pasting relevant parts of Shaun's response below:
1.) Manually obtain and verify the thumbprint using the procedure described here[1].
"ThumbprintList" = "6040DB92306CC8BCEB31CACAC88D107430B16AFF"
2.) Create the OIDC identity provider using the AWS Cli [2].
For example: $ aws iam create-open-id-connect-provider --cli-input-json file://oidc.json Note - the format would be:
aud Audience Must be your Firebase project ID, the unique identifier for your Firebase project, which can be found in the URL of that project's console.
iss Issuer Must be https://securetoken.google.com/<projectId>, where is the same project ID used for aud above.
Content for file://oidc.json: (replace with your Project ID)
{
"Url": "https://securetoken.google.com/<Firebase Client ID>",
"ClientIDList": [ "<Firebase Client ID>" ],
"ThumbprintList": [ "6040DB92306CC8BCEB31CACAC88D107430B16AFF" ]
}
[1] http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
[2] http://docs.aws.amazon.com/cli/latest/reference/iam/create-open-id-connect-provider.html

Related

Vault csi provider in gcp

I'm trying to run Vault CSI provider but I'm getting the following error in my app pod:
MountVolume.SetUp failed for volume "secrets-store-inline" : rpc error: code = Unknown desc = failed to mount secrets store objects for pod vault/my-service-9b78df688-8xnql, err: rpc error: code = Unknown desc = error making mount request: failed to login: Error making API request. Namespace: vault URL: POST https://vault.craft-code.com/v1/auth/gcp/login Code: 400. Errors: * unable to get public key for signed JWT: unable to get public key "xxxxx" for JWT subject "system:serviceaccount:vault:service-web-app": googleapi: Error 400: Request contains an invalid argument.
According to the doc, before login to vault google cloud should issue jwt credential to be able to login in vault. I'm ussing terraform but I don't know how to do that. Could something explain it?
Once the service account and key have been created, the private key can be used to generate the JWT token needed to login to Vault.
To configure a Google Cloud service account to issue a JWT token before it can be used to login to Vault, you need to complete the following steps:
Create a service account in the Google Cloud platform.
Download the JSON key file associated with the service account.
Configure the Vault server to use the GCP auth backend and provide
the JSON key file for the service account.
Configure the Google Cloud IAM roles for the service account in order
to grant it access to the Vault server.
Get the JWT token from the service account and use it to authenticate
with Vault.
Refer to this doc also

Unable to access AWS account through terraform AWS provider --

I'm facing a issue, status code is:401
"creating ec2 instance: authfailure: aws was not able to validate the provided access credentials │ status code: 401, request id: d103063f-0b26-4b84-9719-886e62b0e2b1"
the instance code:
resource "aws_instance" "test-EC2" {
instance_type = "t2.micro"
ami = "ami-07ffb2f4d65357b42"
}
I have checked the AMI region still not working
any help would be appreciated
I am looking for a way to create and destroy tokens via the management console provided by AWS. I am learning about terraform AWS provider which requires an access key, a secret key and a token.
As stated in the error message :
creating ec2 instance: authfailure: aws was not able to validate the provided access credentials │ status code: 401, request id: d103063f-0b26-4b84-9719-886e62b0e2b1".
It is clear that terraform is not able to authenticate itself using terraform AWS-provider.
You have to have a provider block in your terraform configuration to use one of the supported ways to get authenticated.
provider "aws" {
region = var.aws_region
}
In general, the following are the ways to get authenticated to AWS via the AWS-terraform provider.
Parameters in the provider configuration
Environment variables
Shared credentials files
Shared configuration files
Container credentials
Instance profile credentials and region
For more details, please take a look at: https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration
By default, if you are already programmatically signed in to your AWS account AWS-terraform provider will use those credentials.
For example:
If you are using aws_access_key_id and aws_secret_access_key to authenticate yourself then you might have a profile for these credentials. you can check this info in your $HOME/.aws/credentials config file.
export the profile using the below command and you are good to go.
export AWS_PROFILE="name_of_profile_using_secrets"
If you have a SSO user for authentication
Then you might have a sso profile available in $HOME/.aws/config In that case you need to sign in with the respective aws sso profile using the below command
aws sso login --profile <sso_profile_name>
If you don't have a SSO profile yet you can also configure it using the below commands and then export it.
aws configure sso
[....] # configure your SSO
export AWS_PROFILE=<your_sso_profile>
Do you have an aws provider defined in your terraform configuration?
provider "aws" {
region = var.aws_region
profile = var.aws_profile
}
if you are running this locally, please have an IAM user profile set (use aws configure) and export that profile in your current session.
aws configure --profile xxx
export AWS_PROFILE=xxx
once you have the profile set, this should work.
If you are running this deployment in any pipleine like Github Action, you could also make use of OpenId connect to avoid any accesskey and secretkey.
Please find the detailed setup for OpenId connect here.

"The caller does not have permission" when signing GCP storage file URL from AWS lambda

I am trying to sign URL in GCP storage from AWS EC2 or Lambda, I have generated a JSON file for permissions providing my AWS account ID and role which is given to EC2 or Lambda. When I call sign URL even with storage admin or owner permission I get: Error: The caller does not have permission.
I used the code provided by GCP documentation.
const {Storage} = require('#google-cloud/storage');
const storage = new Storage();
const options = {
version: 'v4',
action: 'read',
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
};
// Get a v4 signed URL for reading the file
const [url] = await storage
.bucket(bucketName)
.file(fileName)
.getSignedUrl(options);
Can anybody tell me what did I miss? What is wrong?
Seems the pro
*** update.
I am creating a service account, granting this service account storage admin to my project, then creating pull in Workload Identity Pools, setting AWS and my AWS account ID, then granting access by my AWS identities matching role, downloading JSON, and putting environment variables - GOOGLE_APPLICATION_CREDENTIALS - path to my JSON file and GOOGLE_CLOUD_PROJECT - my project ID. How to correctly load that clientLibraryConfig.json file to run functions I need?
update ** 2
my clientLibraryConfig JSON has the following content..
{
"type": "external_account",
"audience": "..",
"subject_token_type": "..",
"service_account_impersonation_url": "..",
"token_url": "..",
"credential_source": {
"environment_id": "aws1",
"region_url": "..",
"url": "..",
"regional_cred_verification_url": ".."
}
}
How can I generate an access token in node js SDK from this config file to access GCP storage from AWS ec2?
You have to set up the following permissions for the IAM service account:
Storage Object Creator: This is to create signed URLs.
Service Account Token Creator role: This role enables impersonation
of service accounts to create OAuth2 access tokens, sign blobs, or sign JWTs.
Also, you can try to run locally in GCP to sign the URL with the service account.
You can use an existing private key for a service account. The key can be in JSON or PKCS12 format.
Use the command gsutil signurl and pass the path to the private key from the previous step, along with the name of the bucket and object.
For example, if you use a key stored in the folder Desktop, the following command will generate a signed URL for users to view the object cat.jpegfor for 10 minutes.
gsutil signurl -d 10m Desktop/private-key.json gs://example-bucket/cat.jpeg
If successful, the response should look like this:
URL HTTP Method Expiration Signed URL
gs://example-bucket/cat.jpeg GET 2018-10-26 15:19:52 https://storage.googleapis.
com/example-bucket/cat.jpeg?x-goog-signature=2d2a6f5055eb004b8690b9479883292ae74
50cdc15f17d7f99bc49b916f9e7429106ed7e5858ae6b4ab0bbbdb1a8ccc364dad3a0da2caebd308
87a70c5b2569d089ceb8afbde3eed4dff5116f0db5483998c175980991fe899fbd2cd8cb813b0016
5e8d56e0a8aa7b3d7a12ee1baa8400611040f05b50a1a8eab5ba223fe5375747748de950ec7a4dc5
0f8382a6ffd49941c42498d7daa703d9a414d4475154d0e7edaa92d4f2507d92c1f7e811a7cab64d
f68b5df4857589259d8d0bdb5dc752bdf07bd162d98ff2924f2e4a26fa6b3cede73ad5333c47d146
a21c2ab2d97115986a12c28ff37346d6c2ca83e5618ec8ad95632710b489b75c35697d781c38e&
x-goog-algorithm=GOOG4-RSA-SHA256&x-goog-credential=example%40example-project.
iam.gserviceaccount.com%2F20181026%2Fus%2Fstorage%2Fgoog4_request&x-goog-date=
20201026T211942Z&x-goog-expires=3600&x-goog-signedheaders=host
The signed URL is the string that starts with https://storage.googleapis.com, and it is likely to span multiple lines. Anyone can use the URL to access the associated resource (in this case, cat.jpeg) during the designated time frame (in this case, 10 minutes).
So if this works locally, then you can start configuring Workload Identity Federation to impersonate your service account. In this link, you will find a guide to deploy it.
To access resources from AWS using your Workload Identity Federation you will need to review if the following requirements have been already configured:
The workload identity pool has been created.
AWS has been added as an identity provider in the workload identity
pool (The Google organization policy needs to allow federation from
AWS).
The permissions to impersonate a service account have been granted to the external account.
I will add this guide to configure the Workload Identity Federation.
Once the previous requirements have been completed, you will need to generate the service account credential, this file will only contain non sensitive metadata in order to instruct the library on how to retrieve external subject tokens and exchange them for service accounts tokens, as you mentioned the file could be an config.json and could be generated running the following command:
# Generate an AWS configuration file.
gcloud iam workload-identity-pools create-cred-config \
projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$AWS_PROVIDER_ID \
--service-account $SERVICE_ACCOUNT_EMAIL \
--aws \
--output-file /path/to/generated/config.json
Where the following variables need to be substituted:
$PROJECT_NUMBER: The Google Cloud project number.
$POOL_ID:The workload identity pool ID.
$AWS_PROVIDER_ID: The AWS provider ID.
$SERVICE_ACCOUNT_EMAIL: The email of the service account to
impersonate.
Once you generate the JSON credentials configuration file for your external identity, you can store the path at the GOOGLE_APPLICATION_CREDENTIALS environment variable.
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/config.json
So, with this, the library can automatically choose the right type of client and initialize the credential from the configuration file. Please note that the service account will also need the roles/browser when using external identities with Application Default Credentials in Node.js or you can pass the project ID to avoid the need to grant roles/browser to the service account as is shown in the bellow code:
async function main() {
const auth = new GoogleAuth({
scopes: 'https://www.googleapis.com/auth/cloud-platform'
// Pass the project ID explicitly to avoid the need to grant `roles/browser` to the service account
// or enable Cloud Resource Manager API on the project.
projectId: 'CLOUD_RESOURCE_PROJECT_ID',
});
const client = await auth.getClient();
const projectId = await auth.getProjectId();
// List all buckets in a project.
const url = `https://storage.googleapis.com/storage/v1/b?project=${projectId}`;
const res = await client.request({ url });
console.log(res.data);
}

How can I configure `Authorised Domains` when deploying oidc provider to gcp via terraform?

I am deploying OIDC provider to GCP via terraform. I am using this doc as instruction to set it up:
https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/identity_platform_default_supported_idp_config
It works and I am able to deploy an identity to GCP identity platform. The configuration looks like below:
resource "google_identity_platform_default_supported_idp_config" "idp_config" {
enabled = true
idp_id = "playgames.google.com"
client_id = "client-id"
client_secret = "secret"
}
The problem I have is that I can't find where I can add Authorised Domains. When I open this identity on GCP console, I can add the domain on the right panel like below screenshot. But how can I configure them via terraform?

Cannot test Cognito authenticated API Gateway call in Postman (its an ADMIN_NO_SRP_AUTH pool)

I've managed to successfull login to the API gateway I've made via my iOS device and Cognito. The problem is I'd like to use postman to test the API calls then implement them on the phone. Currently, Postman cannot authenticate (despite AWS saying it can). No matter what I do I get a 401 error (visible in the screen-shots)
What I've tried
Downloaded the postman collection from AWS Api Gateway
Then imported it into postman, and switch the authentication to "AWS Signature"
And Here is a screen shot of the Postman Generated Header Info
If I understand correctly, you are trying to call an API Gateway endpoint that is behind the built-in Cognito Authoriser.
I think you've misunderstood how you call an Cognito Authorised API Gateway:
Authorise against Cognito to get an id_token
Call API Gateway with the Authorization header set to id_token
Renew id_token every hour
By enabling ADMIN_NO_SRP_AUTH you're allowing the first step (sign-in to Cognito) to be simplified so that you can more easily do it manually. (If you hadn't, then you would need to do SRP calculations).
One way to get the id_token is to use the aws cli (further ways are shown in the documentation):
aws cognito-idp admin-initiate-auth --user-pool-id='[USER_POOL_ID]' --client-id='[CLIENT_ID]' --auth-flow=ADMIN_NO_SRP_AUTH --auth-parameters="USERNAME=[USERNAME],PASSWORD=[PASSWORD]"
You can then use the result (AuthenticationResult.IdToken) as the Authorization header in Postman (no need for the AWS v4 signature- that is only for IAM authentication).
n.b. a much fuller explanation with images can be found here.
Here is what I finally did to fix postman auth issues
1) Turned off App Client Secret in the Cognito pool.
2) Ran aws --region us-east-1 cognito-idp admin-initiate-auth --cli-input-json file://gettoken.json
JSON file example
{
"UserPoolId": "us-east-1_**********",
"ClientId": "******************",
"AuthFlow": "ADMIN_NO_SRP_AUTH",
"AuthParameters": {
"USERNAME": "*********",
"PASSWORD": "***********"
}
}
3) Went to Postman > Authorization > Bearer Copied the idToken value into the token field and everything worked.
NOTE: For those wondering if not using a secret client key is safe. See this article.