Access SSM Parameter store value in an aws amplify react js application - reactjs

I have an amplify application built using React JS, I have a scenario for which I am manually storing API keys in my SSM parameter store in my AWS account. However, I want to retrieve/get those values(JSON object) based on a key from my React JS app (client side). So, I have installed the aws-sdk, the AWS JavaScript sdk, and using the below code snipped I am trying to access the ssms parameter store
const AWS = require('aws-sdk');
AWS.config.update({region:'us-east-1'});
const ssm = new AWS.SSM();
const getSecret = async (secretName) => {
console.log(`Getting secret for ${secretName}`);
const params = {
Name: secretName,
WithDecryption: true
};
const result = await ssm.getParameter(params).promise();
return result.Parameter.Value;
};
module.exports = {getSecret};
I am receiving this error on running my application and while accessing the store using the getSecret function.
Unhandled Rejection (CredentialsError): Missing credentials in config,
if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
I believe that amplify configures the environment implicitly but since, the SSM Secrets manager is not supported yet by Amplify hence, I have to use the JS AWS SDK for this purpose. Can anyone help me spot the issue while configuring the service using AWS SDK? Or is there another or a better way to access parameter store from the client side?
Also, after surfing I have found a package named dotenv
Is it okay to store aws credentials in such a way?

Your code to fetch parameter store keys/values shouldn't be at client side considering security implications. It should be done at server-side and functionality can be exposed over endpoint for client-side.
You can read the credentials programmatically something like below:
var AWS = require("aws-sdk");
var credentials = new AWS.SharedIniFileCredentials({profile: 'profile name'});
AWS.config.credentials = credentials;
Refrence:
loading-node-credentials-shared
global-config-object

Related

Bypassing Firestore Security Rules in jest tests

Currently working on a React/Typescript/Firebase Firestore project. When writing Jest-tests for some actions/functions that are called from the UI, I ran into the following problem:
In the test file I'm able to setup the firestore client using the v9 api and make it talk to emulator
const app = initializeApp(config.firebase);
const firestore = getFirestore(app);
connectFirestoreEmulator(firestore, "localhost", 8080);
In addition I also found out how to setup the admin client and make it talk to emulator
process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080";
const serviceAccount = require("../../../my-key.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
...config.firebase
});
The test itself looks something like this:
describe("createCompanyAndRating action", () => {
test("call createCompanyAndRating and make sure it creates a proper rating entity", async () => {
// omitted: set testRatingFormState and other test data that are passed as args and
// pass in the firestore db client
const {
ratingId,
companyId,
} = await createCompanyAndRating({
ratingFormState: testRatingFormState,
visitorId: testVisitorId,
firestore,
});
// verify result by fetching the rating entity from the emulator db using the admin client
const ratingPath = `companies/${companyId}/ratings/${ratingId}`;
const ratingSnap = await admin.firestore().doc(ratingPath).withConverter(ratingConverter).get();
const rating: Rating | undefined = ratingSnap.data();
// omitted: verify result with some Jest expect-statetments...
});
})
My problem is now that the Firestore security rules apply and only authenticated users can write docs in the collections used in the createCompanyAndRating function, so the test already throws an error when calling that function.
In this scenario I'm not interested in testing the security rules per se.
Is there a way to bypass the security rules for the test?
If yes, how do I have to setup the firestore client?
Is there even the possibility to somehow impersonate a user in the test?
In addition, please note that I can't to pass the admin client into the createCompanyAndRating function as the admin client API is different from the v9 firebase API that I'm relying on in the createCompanyAndRating function implementation (tried and it didn't work and not only because some type errors in the way).
Maybe my whole approach is a little misguided and I should rather concentrate on testing the internals of the createCompanyAndRating function where I do a lot of factory stuff that could be tested without db interaction.
Anyway, any help/guidance is much appreciated.
Thanks for confirming that I was looking in the right place (i.e. #firebase/rules-unit-testing). Finally figured out what the problem was, missed an "await" in createCompanyAndRating, so the firestore admin instance wasn't getting the data (and I though it was a admin config issue...) Thanks!

Where do I attach the Execute API policy for React App deployed via ECR -> ECS -> ELB?

I wish to secure my API Gateway using AWS IAM Authorization so that only my React Application and users with the correct policy attached can call the endpoints.
I have managed to test that the policy works when I execute via Postman using AWS Signature as the authorisation method, but I'm having trouble applying this policy to my React Application.
The React Application is deployed using CodePipeline to build a container to ECR, then to deploy the application via ECS. The domain routes to the ELB that is mapped to the reverse proxy of the React Application. I just cannot figure out where to attach the policy so that when the API call is made from the webpage, the authorisation is attached to the request. The endpoints are returning a 403 - Missing Authentication Token error (as expected)
Instead of attaching the IAM role to the application's container, I implemented the headers client side. As I'm using Axios, I used the https://www.npmjs.com/package/aws4-axios package which creates a request interceptor for the signing. The credentials are from a new user created with the policy attached to allow execute-api.
import { aws4Interceptor } from "aws4-axios";
export const postLogin = async () => {
let response;
const interceptor = aws4Interceptor(
{
region: "your region here",
service: "execute-api",
},
{
accessKeyId: "from .env",
secretAccessKey: "from .env",
}
);
axios.interceptors.request.use(interceptor);
try {
response = await axios.post( etc.

Using Saml with Azure AD using Blazer Web assembly

I'm trying to use .NET core Blazer webAssembly client UI from main() and authenticate with Azure AD using SAML with the following code, but getting error. can't figure this out one issue below. any clue is appreciated
there was an error trying to log you in: 'Cannot read property 'redirectUri' of undefined'
OIDC works fine.
Below is my code called from Main in Program.cs
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddHttpClient("BlazorWASMAuthApp.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
.CreateClient("BlazorWASMAuthApp.ServerAPI"));
builder.Services.AddApiAuthorization(); builder.Services.AddAuthenticationCore(); builder.Services.AddAuthorizationCore();
builder.Services.AddAuthentication().AddSaml2(options =>
{
// builder.Configuration.Bind("AzureAd", options.SPOptions.AuthenticateRequestSigningBehavior);
//APP Registration keys Will be moved to Json in subsequent story
options.SPOptions.EntityId = new EntityId("https://localhost:5001/saml2");
//options.SPOptions..Add("https://localhost:5001/saml2/API.Access");
options.IdentityProviders.Add(
new IdentityProvider(
new EntityId("https://sts.windows.net/{Clientid}/"), options.SPOptions)
{
//SingleSignOnServiceUrl = signinURI,
MetadataLocation = ...federationdataxml?clientid={clientid}"
});
;
})
.AddCookie();
The most common errors as per ms docs are caused by incorrect configuration
Depending on the requirements of the scenario, a missing or incorrect
Authority, Instance, Tenant ID, Tenant domain, Client ID, or Redirect
URI prevents an app from authenticating clients.
Running the app at a different port than is configured in the Redirect
URI of the Identity Provider's app registration.
Please check if the cause is missing return url parameter in configuration in your code provided:
options.SPOptions.ReturnUrl = new Uri("https://localhost:5001/authentication/azurecallback"); which comes after
options.SPOptions.EntityId = new EntityId("https://localhost:5001/saml2");
else check Portal side configurations.
While registering API , redirect uri is set as web and its field is left empty and api is exposed from Expose api .
But When registering client app , redirect uri must be set ,hope you have done so.
client app > go active directory b2c >give name >select supported account>redirect uri >select SPA-give redirect ur like https://localhost:5001/authentication/login-callback
(format of uri : https://localhost:{PORT}/authentication/login-callback.)
This 'authentication/login-callback' must be present in your code configuration too.
From reference
NOTE: The default port for an app running on Kestrel is 5001. If the
app is run on a different Kestrel port, use the app's port. For IIS
Express, the randomly generated port for the app can be found in the
Server app's properties in the Debug panel. Since the app doesn't
exist at this point and the IIS Express port isn't known, return to
this step after the app is created and update the redirect URI. A
remark appears in the Create the app section to remind IIS Express
users to update the redirect URI.
So Check the port running and update the redirect uri if not done.
References:
Reference 1
Reference 2
Cors

Error: AWS Web RTC Verification with Cognito

I am trying to connect my javascript app AWS WebRTC with a Cognito user to get its credentials dynamically but faced the following error code:
json.js:52 Uncaught (in promise) CredentialsError: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
I have done hard coding my credentials into the configuration and it has work successfully, however that's a bad practice hence I am trying to get AWS Web RTC credentials via my Cognito user. I have setup user pool and link in to my federal identities already. The credentials are now managed by AWS Amplify which loads AWS user profile from config file (./aws/credentials).
Following this two guides:
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-integrating-user-pools-with-identity-pools.html
https://docs.aws.amazon.com/cognito/latest/developerguide/getting-credentials.html
I've written the following snippet to get my credentials but now faced the error.
AWS.config.region = '<REGION>';
AWS.config.update({
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: '<Region>:<IdentitiyPoolID>',
Logins: {
'cognito-idp.<Region>.amazonaws.com/<UserPoolID> ': <id token from cognito>,
},
}),
});
var accessKeyId;
var secretAccessKey;
AWS.config.credentials.get(function () {
accessKeyId = AWS.config.credentials.accessKeyId;
secretAccessKey = AWS.config.credentials.secretAccessKey;
});
const state = {
accessKeyId: accessKeyId,
secretAccessKey: secretAccessKey,
region: 'region',
}
async function startPlayerForViewer();
Any helps is much appreciated ! Cant find much updated resources/examples online.
credentials.get() is an async operation that receives the keys in a callback, while the state definition happens before that callback is received. Hence, the keys are not set. You need to ensure that you define the state after the callback and ensure that the connection happens afterwards.

How does Gatsby application access Azure Key Vault

I have sucessfully deployed my Gatsby App to Azure as per these instructions. This is a separate resource from a "normal" web app. The "normal web app would be deployed to the App Service resource but for Gatsby it is deployed to a different Static Web Page Reqource. So the URL now has the form https://<generated name>.azurestaticapps.net where the generated-name is NOT the application name. So it seems that the instructions for hooking the web service up with the key vault have some holes to be filled in. What are the steps that I need to take to connect my Gatsby App to my azure key vault during development and on the production site?
Error: EnvironmentCredential is not supported in the browser.
In your case, use ClientSecretCredential instead of others.
Make sure you have done the Prerequisites, then in your code, use ClientSecretCredential, pass the tenantId, clientId, clientSecret of your service principal to it, it should be something like below, retrievedSecret.value is the value of the secret.
const { ClientSecretCredential } = require("#azure/identity");
const { SecretClient } = require("#azure/keyvault-secrets");
const keyVaultName = "xxxx";
const KVUri = "https://" + keyVaultName + ".vault.azure.net";
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
const client = new SecretClient(KVUri, credential);
const retrievedSecret = await client.getSecret(secretName);

Resources