widdix / aws-cf-templates

Free Templates for AWS CloudFormation
https://templates.cloudonaut.io/
Apache License 2.0
2.75k stars 1.38k forks source link

state/rds-postgres Security Group #456

Closed claytondaley closed 4 years ago

claytondaley commented 4 years ago

TemplateID: state/rds-postgres Region: us-east-1

I need to create an RDS Postgres instance and give permission to WorkSpaces. Unfortunately, the Security Group ID for the Workspaces is not available in CloudFormation (it's created by/attached to the Directory Service). As a result, I can't even "fake" a ParentClientStack and I hate creating Security Groups that I'm not using.

I'd like to suggest the following:

This ensures that the module can be used in situations that can't be adapted to the ParentClientStack pattern.

P.S. If I wanted to expose the DB to more than two security groups, I'd run into a similar issue. With just 2, I should be able to hijack Client and Bastion. The third has no way to inject it into the DB (and no way to access the internal SG). I assume this could happen if e.g. you have a separate security group for microservices (or groups of microservices) that shared the same database server.

michaelwittig commented 4 years ago

The idea is that you would attach the security group from stage/client-sg.yaml to your workspace. Looks like you can only attach one custom security group to a workspace. So I'm not sure if that works for you.

Otherwise, it might be easier to export the security group id (as you suggest) of the database from state/rds-postgres.yaml so that you can add your own ingress rule to whitelist your workspace.

claytondaley commented 4 years ago

It may not be universally true, but it seems to me that client-sg is basically the Egress SG for services. Ingress SGs for services are injected from e.g. ALB/NLB modules.

A single, monolithic Egress group works well in most cases (and is a perfect default), but it's not hard to imagine cases where it's not ideal. For example, what if you want to give different services access to different internal APIs that don't have intrinsic authentication. The instant you need to provide different Egress rules, you need to use multiple client-sgs. My Service + Admin groups is another reason to have separate SGs. Since most people won't want to spin up multiple copies of RDS and services may require access to the same Elasticache instance for messaging, I think these stacks need a way to support Ingress from multiple SGs.

I'm not suggesting you remove ParentClientStack since it's a very user-friendly default. ParentClientStack# would certainly cover more cases, but requires a bunch of YAML to support a reasonable number of SGs and is limited to that number. By contrast, if RDS exposes its SG ID, I can make as many rules as I need. Since it's an "advanced mode", I'm less worried about making it user friendly, but it'd be trivial to make an Ingress stack that accepts a ParentIngressStack and ParentEgressStack.

===

In my case, you literally cannot can't attach a SG to a Workspace in CF. FWIW you can't much with Workspaces/Directories in CF, but I'm going to work on Custom Resources to get it minimally usable. However, the ::MicrosoftAD directory automatically creates two SGs:

image

The *_workspaceMembers is automatically attached to all new Workspaces. I could wrap that ID in the client-sg interface, but I expect to add ECS-based admin applications in the future. At that point, I'm going to need (at least) a second SG so I'm trying to plan/build for that future.

michaelwittig commented 4 years ago

Can't you use https://docs.aws.amazon.com/workspaces/latest/api/API_ModifyWorkspaceCreationProperties.html CustomSecurityGroupId to attach the client-sg to the workspace?

ambsw-technology commented 4 years ago

Yes that would let me attach the Client SG to Workspaces, but that's still only one source of ingress to RDS. Here's a case that literally cannot be handled by the Client SG pattern:

I keep circling back to the benefits of exposing the RDS SG since it provides support for advanced networking strategies that you aren't going to want to hardcode. In this case, something like -IngressSgId seems like a good future-proof naming scheme. The module could be passed to other modules that want to allow Ingress to the RDS server.

ambsw-technology commented 4 years ago

While the endpoint service creates a huge problem, even a VPC Peer would likely be problematic. The source of the admin connection would necessarily be the SG on the other VPC. So we're back to (at minimum) a service SG and an admin SG. In theory, the bastion could be hijacked for that second SG, but it's IMHO messy to force me to specify the bastion SG so early in the process. I don't want a hard dependency from my application to my admin environment, It makes it very hard to reconfigure that environment.

michaelwittig commented 4 years ago

I'm fine with exposing the security group id as an output.

ambsw-technology commented 4 years ago

Do you have a preferred name? The name I suggested was really motivated by the discussion in cfn-modules which I now realize is really not in-scope here.

michaelwittig commented 4 years ago

I see. Maybe just SecurityGroupId?

michaelwittig commented 4 years ago

merged