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

Add secret manager in weather-dl. #374

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,15 @@ target_template=gs://ecmwf-downloads/hres-single-level/{}.nc
partition_keys=
date
[parameters.deepmind]
api_key=KKKKK1
api_url=UUUUU1
secret_key=projects/PROJECT_NAME/secrets/SECRET_NAME/versions/1
Comment on lines -202 to +201
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a separate section that demos secrets mgr. Users should see examples of both ways of adding keys.

[parameters.research]
api_key=KKKKK2
api_url=UUUUU2
secret_key=projects/PROJECT_NAME/secrets/SECRET_NAME/versions/1
[parameters.cloud]
api_key=KKKKK3
api_url=UUUUU3
secret_key=projects/PROJECT_NAME/secrets/SECRET_NAME/versions/1
```

Note: Here, secret_key is the [secret-manager](https://cloud.google.com/secret-manager) key with value like this: {"api_url": "URL", "api_key": "KEY"}
dabhicusp marked this conversation as resolved.
Show resolved Hide resolved

## `selection` Section

_Parameters used to select desired data_
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"google-cloud-spanner==1.19.3",
"google-cloud-videointelligence==1.16.3",
"google-cloud-vision==1.0.2",
"google-cloud-secret-manager==2.16.2",
"apache-beam[gcp]==2.40.0",
]

Expand Down
29 changes: 22 additions & 7 deletions weather_dl/download_pipeline/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import typing as t
import numpy as np
from collections import OrderedDict
from google.cloud import secretmanager
from urllib.parse import urlparse

from .clients import CLIENTS
Expand Down Expand Up @@ -460,6 +461,23 @@ def prepare_target_name(config: Config) -> str:
return target


def get_secret(secret_key: str) -> t.Dict:
Copy link
Collaborator

@alxmrs alxmrs Aug 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: please return a t.TypedDict so we know what keys to look for.

"""Retrieve the secret value from the Google Cloud Secret Manager.

Parameters:
secret_key (str): The name or identifier of the secret in the Google
Cloud Secret Manager.

Returns:
dict: A dictionary containing the retrieved secret data.
"""
client = secretmanager.SecretManagerServiceClient()
response = client.access_secret_version(request={"name": secret_key})
payload = response.payload.data.decode("UTF-8")
secret_dict = json.loads(payload)
return secret_dict


def get_subsections(config: Config) -> t.List[t.Tuple[str, t.Dict]]:
"""Collect parameter subsections from main configuration.

Expand All @@ -471,17 +489,14 @@ def get_subsections(config: Config) -> t.List[t.Tuple[str, t.Dict]]:
For example:
```
[parameters.alice]
api_key=KKKKK1
api_url=UUUUU1
secret_key=projects/PROJECT_NAME/secrets/SECRET_NAME/versions/1
[parameters.bob]
api_key=KKKKK2
api_url=UUUUU2
secret_key=projects/PROJECT_NAME/secrets/SECRET_NAME/versions/1
[parameters.eve]
api_key=KKKKK3
api_url=UUUUU3
secret_key=projects/PROJECT_NAME/secrets/SECRET_NAME/versions/1
Comment on lines +492 to +496
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep these examples.

```
"""
return [(name, params) for name, params in config.kwargs.items()
return [(name, get_secret(params.get('secret_key'))) for name, params in config.kwargs.items()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should support both API keys and secrets manager.

if isinstance(params, dict)] or [('default', {})]


Expand Down
26 changes: 26 additions & 0 deletions weather_dl/download_pipeline/parsers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
# limitations under the License.
import datetime
import io
import json
import unittest
from unittest.mock import patch, MagicMock

from .manifest import MockManifest, Location
from .parsers import (
date,
get_secret,
parse_config,
process_config,
_number_of_replacements,
Expand Down Expand Up @@ -538,6 +541,29 @@ def test_cfg_parses_parameter_subsections(self):
},
})

@patch("weather_dl.download_pipeline.parsers.secretmanager.SecretManagerServiceClient")
def test_get_secret_success(self, mock_secretmanager):
secret_data = {
"api_url": "https://example.com/api",
"api_key": "my_secret_api_key"
}
mock_response = MagicMock()
mock_response.payload.data.decode.return_value = json.dumps(secret_data)
mock_secretmanager.return_value.access_secret_version.return_value = (
mock_response)

api_key = "projects/my-project/secrets/my-secret/versions/latest"
dabhicusp marked this conversation as resolved.
Show resolved Hide resolved
result = get_secret(api_key)
self.assertEqual(result, secret_data)

@patch("weather_dl.download_pipeline.parsers.secretmanager.SecretManagerServiceClient")
def test_get_secret_failure(self, mock_secretmanager):
mock_secretmanager.return_value.access_secret_version.side_effect = (
Exception("Error retrieving secret"))
api_key = "projects/my-project/secrets/my-secret/versions/latest"
with self.assertRaises(Exception):
get_secret(api_key)


class HelpersTest(unittest.TestCase):

Expand Down
1 change: 1 addition & 0 deletions weather_dl/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"google-cloud-spanner==1.19.3",
"google-cloud-videointelligence==1.16.3",
"google-cloud-vision==1.0.2",
"google-cloud-secret-manager==2.16.2",
"apache-beam[gcp]==2.40.0",
]

Expand Down
Loading