Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

state/rds-postgres Security Group #456

Closed
claytondaley opened this issue Jun 30, 2020 · 9 comments · Fixed by #470
Closed

state/rds-postgres Security Group #456

claytondaley opened this issue Jun 30, 2020 · 9 comments · Fixed by #470

Comments

@claytondaley
Copy link
Contributor

claytondaley commented Jun 30, 2020

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:

  • Make ParentClientStack optional
  • Create the DB Security Group and conditionally add the ingress for ParentClientStack
  • Output/Export the DB Security Group

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
Copy link
Contributor

michaelwittig commented Jul 2, 2020

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
Copy link
Contributor Author

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
Copy link
Contributor

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
Copy link
Contributor

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 have a client who requires public IPs on my side of the VPN. The automatic way to do this on AWS is to reserve a /27 range and assign it to the subnets accessible across the VPN.
  • Since I'm using this range in a private VPC (not as public addresses), I can use this same range for an arbitrary number of clients. However, I can't e.g. VPC peer from my admin VPC to multiple VPCs that use the same IP range.
  • Unless I want to mess with a manual NAT solution, I need to use an Endpoint Service. This approach uses a VPC endpoint in my address range, masking the source CIDR. On the client side, my connections look like they're sourced from the NLB's IP addresses.
  • As you know NLBs don't have a SG. I can use this package to get the NLB IP addresses in CF, but I still need to add IP-based rules to the RDS security group.

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
Copy link
Contributor

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
Copy link
Contributor

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

@ambsw-technology
Copy link
Contributor

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
Copy link
Contributor

I see. Maybe just SecurityGroupId?

@michaelwittig
Copy link
Contributor

merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants