-
Notifications
You must be signed in to change notification settings - Fork 1.1k
chore: IAM Validation added for fail-safe. #3072
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
base: main
Are you sure you want to change the base?
chore: IAM Validation added for fail-safe. #3072
Conversation
Summary of ChangesHello @pratickchokhani, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the robustness and fail-safety of the Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
597b5c8 to
8974d7c
Compare
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (34.69%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #3072 +/- ##
============================================
+ Coverage 50.41% 50.44% +0.03%
- Complexity 5022 5051 +29
============================================
Files 970 977 +7
Lines 59609 59782 +173
Branches 6507 6512 +5
============================================
+ Hits 30050 30156 +106
- Misses 27436 27497 +61
- Partials 2123 2129 +6
🚀 New features to boost your workflow:
|
8974d7c to
fab36a4
Compare
026faff to
a832363
Compare
9de79c9 to
5ab4b26
Compare
|
|
||
| private CloudResourceManager createCloudResourceManagerService() | ||
| throws IOException, GeneralSecurityException { | ||
| if (resourceManagerForTesting != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you want to inject it into the class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do that. But that will only help in testing purpose.
My thinking was that if IAMpermissionsChecker is initialized by the user at class level and is never destroyed, then the resource manager will also never be destroyed.
Hence, initialized later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are mixing testing code in main code. injecting would ensure decoupling and avoids doing stuff like if test code. just a bit cleaner to read IMO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have moved this to constructur.
| private IAMCheckResult check( | ||
| CloudResourceManager resourceManager, List<String> requiredPermissions) { | ||
| HashSet<String> grantedPermissions = | ||
| new HashSet<>(checkPermission(resourceManager, projectIdResource, requiredPermissions)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we only checking at project level? should we fallback to more granular level as well?
e.g., if user/role has required permissions at say, spanner instance or database level?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The testIam API is not to specific on how to validate permissions at instance or database level.
Few of my experiments failed on that part. We can do a followup on figuring out if granular permission is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The testIam API is not to specific on how to validate permissions at instance or database level.
Could you say more about this? The TestIamPermissionsRequest takes resource as an argument, which can be instance or database. are you saying there is no way to specify them?
my concern here is that this may cause permission failures even though user may have required permissions and hence may be confusing to them.
| return new IAMCheckResult(projectIdResource, missingPermissions); | ||
| } | ||
|
|
||
| private List<String> checkPermission( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the difference between this and previous "check" method? their signature looks similar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This require resource name. This was made from the perspective when we are checking permission at resource level.
Currently, there isn't much difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like a helper method. In which case, it might make sense to call the other method from here (or vice versa) to not duplicate the flows.
v1/src/main/java/com/google/cloud/teleport/spanner/iam/IAMPermissionsChecker.java
Outdated
Show resolved
Hide resolved
| */ | ||
| public IAMCheckResult check(List<IAMResourceRequirements> requirements) { | ||
| try { | ||
| CloudResourceManager resourceManager = createCloudResourceManagerService(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be injected at class level?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is designed for the check method to be called only once. This reduces IAM validation call.
Caller is suppose to aggregate all the permissions and call the Check method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add this in the docs to make it clear that it is an expensive call it should not be called frequently.
Though, just double checking if there is any harm in making it a class level variable as suggested ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have moved this to constructor.
| import java.util.List; | ||
|
|
||
| public class IAMRequirementsCreator { | ||
| private static final List<String> SPANNER_PERMISSIONS = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious: why do we have a single list? shouldnt the list be use case specific?
for example, I see same list for both import and export. shouldnt their permission list be different?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be a list that caller (user of the module) passes into this module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The goal of this class is to have separate lists. For the export pipeline, we can have a separate list within this class.
The thought process is that, we do not need too many distinct lists and there will be duplicates.
For export, I can create a instances list and databases create or drop. But rest should be there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case call this the DEFAULT_SPANNER_PERMISSIONS or so. Again with comments to cover the thought process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| import java.util.List; | ||
|
|
||
| /** Represents the IAM permissions required on a specific GCP resource. */ | ||
| public class IAMResourceRequirements { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this class seems like a holder for an arraylist.
how are we thinking of growing/extending this class, if in future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will grow when we will be checking permissions per resource.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to Rohit's comment here. Please remove if not needed or add docs on where it might be needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have added the comment.
| } | ||
| } | ||
|
|
||
| private static void validateRequiredPermissions(ExportPipelineOptions options) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i see this code is duplicated across pipelines. would it make sense to push it down as an API in the IAM checker module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It needs to be per-Template. For Import and export the code is same. But this will change when we shift to other templates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you pl help be understand better with an example, on how it might deviate? and may be leave a comment for future code readers
5ab4b26 to
441067b
Compare
441067b to
3bc834f
Compare
| new IAMPermissionsChecker(gcpOptions.getProject(), gcpOptions); | ||
| IAMCheckResult missingPermission = | ||
| iamPermissionsChecker.check(Collections.singletonList(spannerRequirements)); | ||
| if (missingPermission.isSuccess()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the naming is a little confusing. Does missingPermission.isSuccess mean the permission is there or the check failed or does it mean the check succeeded ?
Try to avoid double negatives where possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the code reading - i would suggest renaming this to permissionCheck or something rather than missing permissions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| return new ArrayList<>(missingPermissions); | ||
| } | ||
|
|
||
| public boolean isSuccess() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: rename method to permissionsAvailable or something clearer.
isSuccess could be misunderstood as the check API is successful or so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| */ | ||
| public IAMCheckResult check(List<IAMResourceRequirements> requirements) { | ||
| try { | ||
| CloudResourceManager resourceManager = createCloudResourceManagerService(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add this in the docs to make it clear that it is an expensive call it should not be called frequently.
Though, just double checking if there is any harm in making it a class level variable as suggested ?
| .collect(Collectors.toList()); | ||
|
|
||
| return new IAMCheckResult(projectIdResource, missingPermissions); | ||
| } catch (IOException | GeneralSecurityException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add an info logger here with the error message. It is possible that the parent hides this in another error.
| return new IAMCheckResult(projectIdResource, missingPermissions); | ||
| } | ||
|
|
||
| private List<String> checkPermission( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like a helper method. In which case, it might make sense to call the other method from here (or vice versa) to not duplicate the flows.
| import java.util.List; | ||
|
|
||
| public class IAMRequirementsCreator { | ||
| private static final List<String> SPANNER_PERMISSIONS = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case call this the DEFAULT_SPANNER_PERMISSIONS or so. Again with comments to cover the thought process.
| import java.util.List; | ||
|
|
||
| /** Represents the IAM permissions required on a specific GCP resource. */ | ||
| public class IAMResourceRequirements { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to Rohit's comment here. Please remove if not needed or add docs on where it might be needed.
manitgupta
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Only the
IAMPermissiomsCheckerseems to have a UT, do we need UTs for the other classes that have been added? - Did you get a resolution on the placement of this lib? There was a discussion on
v1v/sv2and how that would work out.
5f0a0cb to
42e6235
Compare
42e6235 to
92d29c7
Compare
New IAM Validation Utilities: Introduced a set of new utility classes (IAMCheckResult, IAMPermissionsChecker, IAMRequirementsCreator, IAMResourceRequirements) to programmatically check IAM permissions for Google Cloud Platform resources.
Cloud Resource Manager API Integration: Added the google-api-services-cloudresourcemanager dependency to the pom.xml to enable interaction with the Cloud Resource Manager API for permission checks.
Spanner Permission Validation: Integrated a validateRequiredPermissions method into the Import and Export pipeline template to perform pre-execution IAM checks for Spanner resources, ensuring necessary permissions are present for the pipeline to run successfully.