-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ENG-2790] Fix broken p0 kubeconfig command (#129)
This PR unbreaks the `p0 kubeconfig` command. Some values and structures got changed around in the k8s integration config and responses from the backend: - Required AWS IDC metadata is no longer found in the `eksGenerated` object; it's now in `awsResourcePermission` - AWS account ID is no longer stored separately in the k8s integration configuration, and now is extracted from the EKS cluster ARN - `provider` was renamed `hosting` in the k8s integration configuration It also adds some minor quality-of-live improvements to the `p0 kubeconfig` command, such as utilizing `spinUntil()` for some of the longer `await`s, and adds a more robust and reusable simple AWS ARN parser.
- Loading branch information
1 parent
7d01bd7
commit a541036
Showing
6 changed files
with
204 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/** Copyright © 2024-present P0 Security | ||
This file is part of @p0security/cli | ||
@p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. | ||
@p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>. | ||
**/ | ||
import { parseArn } from "../utils"; | ||
|
||
describe("parseArn() function", () => { | ||
it.each([ | ||
"badarn:aws:ec2:us-east-1:123456789012:vpc/vpc-0e9801d129EXAMPLE", // Bad prefix | ||
":aws:ec2:us-east-1:123456789012:vpc/vpc-0e9801d129EXAMPLE", // Missing prefix | ||
"arn:aws:ec2:us-east-1:123456789012", // Too few elements | ||
])('Raises an "Invalid ARN" error', (arn) => { | ||
expect(() => parseArn(arn)).toThrow("Invalid AWS ARN"); | ||
}); | ||
|
||
it("Parses a valid ARN with all fields correctly", () => { | ||
const arn = "arn:aws:ec2:us-east-1:123456789012:vpc/vpc-0e9801d129EXAMPLE"; | ||
|
||
const parsed = parseArn(arn); | ||
|
||
expect(parsed).toEqual({ | ||
partition: "aws", | ||
service: "ec2", | ||
region: "us-east-1", | ||
accountId: "123456789012", | ||
resource: "vpc/vpc-0e9801d129EXAMPLE", | ||
}); | ||
}); | ||
|
||
it("Parses a valid ARN with colons in the resource correctly", () => { | ||
// Note: This is not the format we would expect an EKS ARN to actually be in (it should | ||
// use a / instead of a : in the resource); this is just for unit testing purposes. | ||
const arn = "arn:aws:eks:us-west-2:123456789012:cluster:my-testing-cluster"; | ||
|
||
const parsed = parseArn(arn); | ||
|
||
expect(parsed).toEqual({ | ||
partition: "aws", | ||
service: "eks", | ||
region: "us-west-2", | ||
accountId: "123456789012", | ||
resource: "cluster:my-testing-cluster", | ||
}); | ||
}); | ||
|
||
it("Parses a valid ARN with no region correctly", () => { | ||
const arn = "arn:aws:iam::123456789012:user/johndoe"; | ||
|
||
const parsed = parseArn(arn); | ||
|
||
expect(parsed).toEqual({ | ||
partition: "aws", | ||
service: "iam", | ||
region: "", | ||
accountId: "123456789012", | ||
resource: "user/johndoe", | ||
}); | ||
}); | ||
|
||
it("Parses a valid ARN with no account ID correctly", () => { | ||
// Note: This is not a valid SNS ARN; they would ordinarily have an account ID. This is | ||
// just for unit testing purposes. | ||
const arn = "arn:aws-us-gov:sns:us-east-1::example-sns-topic-name"; | ||
|
||
const parsed = parseArn(arn); | ||
|
||
expect(parsed).toEqual({ | ||
partition: "aws-us-gov", | ||
service: "sns", | ||
region: "us-east-1", | ||
accountId: "", | ||
resource: "example-sns-topic-name", | ||
}); | ||
}); | ||
|
||
it("Parses a valid ARN with no region or account ID correctly", () => { | ||
const arn = "arn:aws-cn:s3:::my-corporate-bucket"; | ||
|
||
const parsed = parseArn(arn); | ||
|
||
expect(parsed).toEqual({ | ||
partition: "aws-cn", | ||
service: "s3", | ||
region: "", | ||
accountId: "", | ||
resource: "my-corporate-bucket", | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** Copyright © 2024-present P0 Security | ||
This file is part of @p0security/cli | ||
@p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. | ||
@p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>. | ||
**/ | ||
const ARN_PATTERN = | ||
/^arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):([^:]*):([^:]*):([^:]*):(.*)$/; | ||
|
||
/** | ||
* Parses out Amazon Resource Names (ARNs) from AWS into their components. Note | ||
* that not all components are present in all ARNs (depending on the service; | ||
* for example, S3 ARNs don't have a region or account ID), and the final | ||
* component of the ARN (`resource`) may contain its own internal structure that | ||
* is also service-dependent and which may also include colons. In particular, | ||
* quoting the Amazon docs: "Be aware that the ARNs for some resources omit the | ||
* Region, the account ID, or both the Region and the account ID." | ||
* | ||
* @param arn The ARN to parse as a string. | ||
* @return A structure representing the components of the ARN. All fields will | ||
* be defined, but some may be empty strings if they are not present in the ARN. | ||
*/ | ||
export const parseArn = ( | ||
arn: string | ||
): { | ||
partition: string; | ||
service: string; | ||
region: string; | ||
accountId: string; | ||
resource: string; | ||
} => { | ||
// Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html | ||
const invalidArnMsg = `Invalid AWS ARN: ${arn}`; | ||
const match = arn.match(ARN_PATTERN); | ||
|
||
if (!match) { | ||
throw invalidArnMsg; | ||
} | ||
|
||
const [_, partition, service, region, accountId, resource] = match; | ||
|
||
// We know these are all defined based on the regex, but TypeScript doesn't. | ||
// Empty string is okay, so explicitly check for undefined. | ||
if ( | ||
partition === undefined || | ||
service === undefined || | ||
accountId === undefined || | ||
region === undefined || | ||
resource === undefined | ||
) { | ||
throw invalidArnMsg; | ||
} | ||
|
||
return { | ||
partition, | ||
service, | ||
region, | ||
accountId, | ||
resource, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters