-
Notifications
You must be signed in to change notification settings - Fork 6.7k
feat(secretmanager): Adding secret rotation samples #13748
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?
feat(secretmanager): Adding secret rotation samples #13748
Conversation
…python-docs-samples into python_expiretime_samples
…python-docs-samples into python_expiretime_samples
Summary of ChangesHello @khilan-crest, 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 significantly enhances the Google Cloud Secret Manager Python samples by introducing a suite of new functionalities. It provides developers with clear, executable examples for advanced secret lifecycle management, including setting and updating expiration times, configuring and modifying secret rotation policies, and integrating with Pub/Sub for notifications. Furthermore, it adds robust examples for managing resource tags on secrets, covering creation, listing, and detachment, for both global and regional secret instances. 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
|
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.
Code Review
This pull request adds a comprehensive set of new samples for Secret Manager, covering secret rotation, expiration, and tagging for both global and regional secrets. The changes are well-structured and the accompanying tests are thorough. I've provided a few suggestions to improve the correctness of the documentation, ensure consistency across the new samples, and address minor issues like timezone handling and typos. Overall, this is a great addition to the repository.
| Args: | ||
| project_id (str): ID of the Google Cloud project | ||
| secret_id (str): ID of the secret to update | ||
| rotation_period_hours (int): New rotation period in hours |
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.
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
| # Update the rotation period of a secret to 60 days | ||
| update_secret_rotation( | ||
| "my-project", | ||
| "my-secret-with-rotation", | ||
| "projects/my-project/topics/my-rotation-topic" | ||
| ) |
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 example usage is incorrect and will raise an error. It passes a topic_name which is not a parameter of the function. Additionally, the comment mentions '60 days' while the code hardcodes the rotation to 48 hours. The example should be corrected to reflect the actual implementation.
| # Update the rotation period of a secret to 60 days | |
| update_secret_rotation( | |
| "my-project", | |
| "my-secret-with-rotation", | |
| "projects/my-project/topics/my-rotation-topic" | |
| ) | |
| # Update the rotation period of a secret to 48 hours | |
| update_secret_rotation( | |
| "my-project", | |
| "my-secret-with-rotation" | |
| ) |
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
| # limitations under the License. | ||
|
|
||
| # [START secretmanager_create_regional_secret_with_rotation] | ||
| from datetime import datetime, timedelta |
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.
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
| count = 0 | ||
|
|
||
| print(f"Tag bindings for {secret_name}:") | ||
| for binding in bindings: | ||
| print(f"- Tag Value: {binding.tag_value}") | ||
| count += 1 | ||
|
|
||
| if count == 0: | ||
| print(f"No tag bindings found for {secret_name}.") |
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.
Using a counter variable count to check if any items were processed is a bit verbose. A more Pythonic approach is to use a boolean flag to track if any bindings were found. This can improve readability.
For example:
found_bindings = False
print(f"Tag bindings for {secret_name}:")
for binding in bindings:
print(f"- Tag Value: {binding.tag_value}")
found_bindings = True
if not found_bindings:
print(f"No tag bindings found for {secret_name}.")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
|
|
||
| # Set next rotation time to 24 hours from now | ||
| next_rotation_time = timestamp_pb2.Timestamp() | ||
| next_rotation_time.FromDatetime(datetime.now() + timedelta(hours=24)) |
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.
Using datetime.now() without a timezone creates a naive datetime object, which can lead to inconsistencies. It's best practice to use timezone-aware objects, especially for APIs. Please use datetime.now(timezone.utc) for consistency and to avoid potential bugs.
| next_rotation_time.FromDatetime(datetime.now() + timedelta(hours=24)) | |
| next_rotation_time.FromDatetime(datetime.now(timezone.utc) + timedelta(hours=24)) |
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
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| import argparse |
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.
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
| count = 0 | ||
|
|
||
| # Use the list_tag_bindings method to get all tag bindings | ||
| request = resourcemanager_v3.ListTagBindingsRequest(parent=parent) | ||
| tag_bindings = tag_bindings_client.list_tag_bindings(request=request) | ||
|
|
||
| # Iterate through the results | ||
| for binding in tag_bindings: | ||
| print(f"- Tag Value: {binding.tag_value}") | ||
| count += 1 | ||
|
|
||
| if count == 0: | ||
| print(f"No tag bindings found for {name}.") |
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.
Using a counter variable count to check if any items were processed is a bit verbose. A more Pythonic approach is to use a boolean flag to track if any bindings were found. This can improve readability.
For example:
found_bindings = False
for binding in tag_bindings:
print(f"- Tag Value: {binding.tag_value}")
found_bindings = True
if not found_bindings:
print(f"No tag bindings found for {name}.")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
| retrived_secret = get_regional_secret.get_regional_secret( | ||
| project_id, location_id, secret_id | ||
| ) | ||
|
|
||
| assert ( | ||
| len(retrived_secret.topics) == 1 | ||
| ), f"Expected 1 topic, got {len(retrived_secret.topics)}" | ||
| assert ( | ||
| retrived_secret.topics[0].name == topic_name | ||
| ), f"Topic mismatch: got {retrived_secret.topics[0].name}, want {topic_name}" |
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.
There's a typo in the variable name retrived_secret. It should be retrieved_secret for correctness and readability.
| retrived_secret = get_regional_secret.get_regional_secret( | |
| project_id, location_id, secret_id | |
| ) | |
| assert ( | |
| len(retrived_secret.topics) == 1 | |
| ), f"Expected 1 topic, got {len(retrived_secret.topics)}" | |
| assert ( | |
| retrived_secret.topics[0].name == topic_name | |
| ), f"Topic mismatch: got {retrived_secret.topics[0].name}, want {topic_name}" | |
| retrieved_secret = get_regional_secret.get_regional_secret( | |
| project_id, location_id, secret_id | |
| ) | |
| assert ( | |
| len(retrieved_secret.topics) == 1 | |
| ), f"Expected 1 topic, got {len(retrieved_secret.topics)}" | |
| assert ( | |
| retrieved_secret.topics[0].name == topic_name | |
| ), f"Topic mismatch: got {retrieved_secret.topics[0].name}, want {topic_name}" |
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
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| import argparse |
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.
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
| retrived_secret = get_secret(project_id, secret_id) | ||
|
|
||
| assert ( | ||
| len(retrived_secret.topics) == 1 | ||
| ), f"Expected 1 topic, got {len(retrived_secret.topics)}" | ||
| assert ( | ||
| retrived_secret.topics[0].name == topic_name | ||
| ), f"Topic mismatch: got {retrived_secret.topics[0].name}, want {topic_name}" |
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.
There's a typo in the variable name retrived_secret. It should be retrieved_secret for correctness and readability.
| retrived_secret = get_secret(project_id, secret_id) | |
| assert ( | |
| len(retrived_secret.topics) == 1 | |
| ), f"Expected 1 topic, got {len(retrived_secret.topics)}" | |
| assert ( | |
| retrived_secret.topics[0].name == topic_name | |
| ), f"Topic mismatch: got {retrived_secret.topics[0].name}, want {topic_name}" | |
| retrieved_secret = get_secret(project_id, secret_id) | |
| assert ( | |
| len(retrieved_secret.topics) == 1 | |
| ), f"Expected 1 topic, got {len(retrieved_secret.topics)}" | |
| assert ( | |
| retrieved_secret.topics[0].name == topic_name | |
| ), f"Topic mismatch: got {retrieved_secret.topics[0].name}, want {topic_name}" |
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
…python-docs-samples into python_expiretime_samples
…-crest/python-docs-samples into python_rotation_samples
…python-docs-samples into python_expiretime_samples
…-crest/python-docs-samples into python_rotation_samples
…python-docs-samples into python_expiretime_samples
…-crest/python-docs-samples into python_rotation_samples
…python-docs-samples into python_expiretime_samples
…-crest/python-docs-samples into python_rotation_samples
Adding secret rotation samples
Fixes #
Note: Before submitting a pull request, please open an issue for discussion if you are not associated with Google.
Checklist
nox -s py-3.9(see Test Environment Setup)nox -s lint(see Test Environment Setup)