Hi, I am trying to set up multiple stacks with Ser...
# help
g
Hi, I am trying to set up multiple stacks with Serverless stack. One for auth, one for the api as I want to keep them separate for other services using the auth service. I need to pass the userpool id as an environement variable to the lambdas in the api stack. I have been attempting to use cloudformation outputs and inputs to do this but it always attempts to build the API stack first rather then the auth stack which then causes an error. Is there a way to define the order the stacks build in? Or is there a better way to pass parameters between stacks (also attempted SSM but run into the same issue)?
f
When you pass something around, behind the scene, the value is added as a CloudFormation export to the auth stack, and then imported by the api stack.
g
Hi frank, so I am already doing that but I am actually using a custom lambda authorizer which I want to pass the userpool id and identity pool id to as environement variables. When I use these references as an environment variable it gives me a cyclic dependency error
COGNITO_USER_POOL_ID: props.auth.cognitoUserPool.userPoolId
Copy code
Error: 'georgeevans-decarbonisation-Auth' depends on 'georgeevans-decarbonisation-ApiStack' (georgeevans-decarbonisation-Auth -> georgeevans-decarbonisation-ApiStack/RestApi/Api/Resource.Ref). Adding this dependency (georgeevans-decarbonisation-ApiStack -> georgeevans-decarbonisation-Auth/UserPool/Resource.Ref) would create a cyclic reference.
the other methods I have tried are
Copy code
COGNITO_USER_POOL_ID: ssm.StringParameter.valueFromLookup(this, `${scope.stage}-${scope.name}-cognitoUserPoolId`),
COGNITO_USER_POOL_ID: cdk.Fn.importValue(`${scope.stage}-${scope.name}-cognitoUserPoolId`),
both try to build the API stack first so cause an error that the variables do not exist
f
Oh I see. Yeah, the
Auth
stack is dependent on the Api’s id from the
Api
stack; and the
Api
stack is dependent on the User pool id from the
Auth
stack.
Hence the cyclical dependency.
We’d need to break one of them.
g
Why is the auth stack dependant on the Api stack out of interest?
Copy code
const userPool = new cognito.UserPool(
      this, "UserPool", {
        userPoolName: `${scope.stage}-${scope.name}-users`,
        standardAttributes: { email: { required: true } },
        passwordPolicy: { tempPasswordValidity: cdk.Duration.days(90) },
        signInCaseSensitive: false,
        signInAliases: { email: true }
      }
    );

    const userPoolClient = new cognito.UserPoolClient(this, "UserPoolClient", {
      userPool,
      disableOAuth: true
    });

    this.auth = new Auth(this, "CognitoAuth", {
      cognito: {
        triggers: { customMessage: "services/core/src/cognito/custom-message.handler" },
        userPool,
        userPoolClient
      }
    });
this is my auth stack and there isnt any reference to the api here?
f
if you are doing something like
auth.attachPermissionsForAuthUsers([api]);
The auth construct needs the api’s id to create it’s policy.
g
ah yeah ok
f
Thinking…
g
I guess I could use raw cdk for the iam permissions connection?
oh actually thats still an issue Im guessing its this permission thats the issue:
Copy code
{
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:eu-west-2:193471113837:zbbio4r583/*",
            "Effect": "Allow"
        },
f
yup
g
This is more into cdk then serverless stack now but I could create a role in a stack and pass that through to each stack and attach the permissions as I go?
f
Instead of
Copy code
auth.attachPermissionsForAuthUsers([api]);
Can you try this
Copy code
const policy = new iam.Policy(this, "AuthPolicy", {
  statements: [
    new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      actions: ["execute-api:Invoke"],
      resources: [`arn:aws:execute-api:${scope.region}:${scope.account}:${api.httpApiId}/*`]
    })
  ],
});
policy.attachToRole(auth.iamAuthRole);
g
looks like that may have worked, just deploying now
yeah thats worked! thanks for your speedy help! 😁
f
Awesome 👍
g
awesome thanks 👍
m
I have a different question but closely related to how to tweak
auth.addPermissionsToAuthRole
. I hope its OK that I raise my question here. Essentially, I have already deployed my Auth sst stack with Cognito User Pools and its working fine for my ReactStaticApp. However, now I have a separate Infrastructure repository in which I created an Api sst stack, but I am struggling to use the same Cognito User pools already deployed for the React app. I have been trying to add IAM authentication (from the already existing User pool) to the Api SST stack by doing something very similar to the solution reported in this thread. My solution gets deployed ok, but does not seem to work (I get HTTP 403 when using my existing Cognito User credentials). I assume this might not work without being able to refer to an instance of the Auth stack? What do you suggest as a solution for reusing an existing Auth/Cognito pools for an Api sst that is deployed in a separate repository?