From 7cad30713f06df6380c7a38cf40d8b220d450ad1 Mon Sep 17 00:00:00 2001 From: Gavin Frazar Date: Mon, 30 Sep 2024 20:26:18 -0700 Subject: [PATCH] display all security group rules for a port range --- .../EnrollRdsDatabase/SingleEnrollment.tsx | 2 +- .../SecurityGroupPicker.tsx | 56 +++++++++++++++++-- .../SecurityGroupRulesDialog.tsx | 25 ++++----- web/packages/teleport/src/config.ts | 2 +- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/web/packages/teleport/src/Discover/Database/EnrollRdsDatabase/SingleEnrollment.tsx b/web/packages/teleport/src/Discover/Database/EnrollRdsDatabase/SingleEnrollment.tsx index 43dede55ed56d..f8d3fa315de5c 100644 --- a/web/packages/teleport/src/Discover/Database/EnrollRdsDatabase/SingleEnrollment.tsx +++ b/web/packages/teleport/src/Discover/Database/EnrollRdsDatabase/SingleEnrollment.tsx @@ -201,7 +201,7 @@ export function SingleEnrollment({ <> {showTable && ( <> - Select an RDS to enroll: + Select an RDS database to enroll: { + const rules = sg.inboundRules.flatMap(rule => + expandSecurityGroupRule(rule) + ); return ( - setViewRulesSelection({ sg, ruleType: 'inbound' }) + setViewRulesSelection({ + name: sg.name, + rules: rules, + ruleType: 'inbound', + }) } > - View ({sg.inboundRules.length}) + View ({rules.length}) ); @@ -120,15 +129,22 @@ export const SecurityGroupPicker = ({ altKey: 'outboundRules', headerText: 'Outbound Rules', render: sg => { + const rules = sg.outboundRules.flatMap(rule => + expandSecurityGroupRule(rule) + ); return ( - setViewRulesSelection({ sg, ruleType: 'outbound' }) + setViewRulesSelection({ + name: sg.name, + rules: rules, + ruleType: 'outbound', + }) } > - View ({sg.outboundRules.length}) + View ({rules.length}) ); @@ -177,3 +193,33 @@ function CheckboxCell({ ); } + +type ExpandedSecurityGroupRule = { + // IPProtocol is the protocol used to describe the rule. + ipProtocol: string; + // FromPort is the inclusive start of the Port range for the Rule. + fromPort: string; + // ToPort is the inclusive end of the Port range for the Rule. + toPort: string; + // Source is IP range, security group ID, or prefix list that the rule applies to. + source: string; + // Description contains a small text describing the source. + description: string; +}; + +// expandSecurityGroupRule takes a security group rule in the compact form that +// AWS API returns, wherein rules are grouped by port range, and expands the +// rule into a list of rules that is not grouped by port range. +// This is the same display format that the AWS console uses when you view a +// security group's rules. +function expandSecurityGroupRule( + rule: SecurityGroupRule +): ExpandedSecurityGroupRule[] { + return rule.cidrs.map(source => ({ + ipProtocol: rule.ipProtocol, + fromPort: rule.fromPort, + toPort: rule.toPort, + source: source.cidr, + description: source.description, + })); +} diff --git a/web/packages/teleport/src/Discover/Shared/SecurityGroupPicker/SecurityGroupRulesDialog.tsx b/web/packages/teleport/src/Discover/Shared/SecurityGroupPicker/SecurityGroupRulesDialog.tsx index b86ce2e306129..b377230a56e76 100644 --- a/web/packages/teleport/src/Discover/Shared/SecurityGroupPicker/SecurityGroupRulesDialog.tsx +++ b/web/packages/teleport/src/Discover/Shared/SecurityGroupPicker/SecurityGroupRulesDialog.tsx @@ -32,8 +32,8 @@ export function SecurityGroupRulesDialog({ viewRulesSelection: ViewRulesSelection; onClose: () => void; }) { - const { ruleType, sg } = viewRulesSelection; - const data = ruleType === 'inbound' ? sg.inboundRules : sg.outboundRules; + const { name, rules, ruleType } = viewRulesSelection; + // expand the list of rules into a list of rules without port range grouping. return ( @@ -44,11 +44,10 @@ export function SecurityGroupRulesDialog({ textAlign="center" >

- {ruleType === 'inbound' ? 'Inbound' : 'Outbound'} Rules for [{sg.name} - ] + {ruleType === 'inbound' ? 'Inbound' : 'Outbound'} Rules for [{name}]

{ - // The AWS API returns an array, however it appears it's not actually possible to have multiple CIDR's for a single rule. - // As a fallback we just display the first one. - const cidr = cidrs[0]; - if (cidr) { - return {cidr.cidr}; + render: ({ source }) => { + if (source) { + return {source}; } return null; }, @@ -80,10 +76,9 @@ export function SecurityGroupRulesDialog({ { altKey: 'description', headerText: 'Description', - render: ({ cidrs }) => { - const cidr = cidrs[0]; - if (cidr) { - return {cidr.description}; + render: ({ description }) => { + if (description) { + return {description}; } return null; }, diff --git a/web/packages/teleport/src/config.ts b/web/packages/teleport/src/config.ts index 217b48e52b7a8..37e99a8a13144 100644 --- a/web/packages/teleport/src/config.ts +++ b/web/packages/teleport/src/config.ts @@ -319,7 +319,7 @@ const cfg = { awsRdsDbRequiredVpcsPath: '/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/requireddatabasesvpcs', awsDatabaseVpcsPath: - '/webapi/sites/:clusterId/integrations/aws-oidc/:name/databasevpcs', + '/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/databasevpcs', awsRdsDbListPath: '/v1/webapi/sites/:clusterId/integrations/aws-oidc/:name/databases', awsDeployTeleportServicePath: